Technical Documentation: PKUanonym/REKCARC-TSC-UHT
ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference
Overview (README.md)
清华大学计算机系课程攻略
Web page: REKCARC-TSC-UHT.readthedocs.io
受浙江大学相关项目启发,创立了本项目。
由于本仓库未启用 git-lfs,因此请不要上传单个超过 100M 的文件,否则 commit 无效。
若要下载单个文件夹,复制该文件夹的网址,粘贴入 DownGit 中,选择 download 即可。
如果您是清华大学学生,可移步 https://git.tsinghua.edu.cn/pkuanonym/REKCARC-TSC-UHT 进行查看并且能节约不少流量。
感谢对本项目贡献的同学:Trinkle23897、LJSthu、shyoshyo、wuhaozhe、choumartin1234、FztTony、VicaYang、duzx16、zerotrac、gjz010、Recursion、linusboyle、namasikanam、JamesZhengYuyu、zx1239856、yaoqs、heheda12345、MashPlant、lwpie、cht33、chenweize1998、will7101、UNIDY2002、yinhaoxuan、zhengkw18、rcy17、prnake、qky18、JamesZFS、Co1lin、3ToThe6、c7w、zhaochenyang20、Maple、yuxuan-z ……以及电脑前的您!
前言
继承自 Trinkle23897 的项目,删去了其中侵权内容。若还有任何侵权内容请在 issues 下指出,非常感谢。
目录
本项目收录的内容见 收录内容
本项目大部分课程的参考书目见 参考书目
贡献
欢迎贡献!
Issue、PR、纠错、资料、选课/考试攻略,完全欢迎!来自大家的关注、维护和贡献,才是让这个攻略继续存在的动力~
如果希望匿名贡献,可以 email 至此邮箱,注明 "REKCARC-TSC-UHT" 即可:[email protected]
贡献方法见 贡献方法
许可
由贡献者编写部分的许可如下:
(Creative Commons BY-SA 4.0) 知识共享署名 - 相同方式共享 4.0 国际许可协议
其他部分的版权归属于其各自的作者。资料仅供参考,请自己判断其适用性。
附录
清华大学学生纪律处分管理规定实施细则
第六章 学术不端、违反学习纪律的行为与处分
第二十一条 有下列违反课程学习纪律情形之一的,给予警告以上、留校察看以下处分:
(一)课程作业抄袭严重的;
(二)实验报告抄袭严重或者篡改实验数据的;
(三)期中、期末课程论文抄袭严重的;
(四)在课程学习过程中严重弄虚作假的其他情形。
大一小学期 Week 3 Python Docs Readme (`大一小学期/Week_3-Python/docs/readme.md`)
使用方法
文档目标
关于大一小学期一些形而上学的课程体验,请参考计算机系的课程攻略文档。与之不同,本文档的目标非常具体。
此文档参考了自 2019 年到 2021 年三年 Python 小学期的要求,综合了暑培课程讲义、往年优秀作业与本人所参与的多个应用爬虫与数据分析的 SRT 工作汇编而成,希望能够为一字班选修了 Python 小学期的同学提供有力的自学预习材料,也之后需要使用相关 Python 工具的同学提供支持。
与暑培内容重叠的部分,汇编者进行了修订,例如为网页爬虫提供了包括 Facebook,Twitter,Youtube 等高强度反爬网页的实例。如果你参与了暑培的部分内容,仍然建议你阅读经过汇编者补充的例子。
暑培课程之外,汇编者扩充更多相应的文档,主要是 BeatifulSoup4,Pandas,Matplotlib,做到了对于小学期内容的全覆盖与降维打击。
内容概述
.
├── CodeReview.md
├── DS_tutorial.pdf
├── Python
│ ├── Numpy.ipynb
│ └── Python\ Advanced\ Topics.ipynb
├── backend
│ ├── Django.md
│ ├── Django_preparation.pdf
│ └── SQL.pdf
├── crawler
│ └── crawler.ipynb
├── readme.md
├── soup
│ ├── BeatifulSoup4.ipynb
│ ├── Pandas.ipynb
│ ├── Pandas_refined.ipynb
│ └── README.md
└── visualize
├── Matplotlib.ipynb
└── README.md
5 directories, 15 files- Python 路径下:Python 基础语法与 Python 进阶(IPython)、Numpy
- Crawler 路径下:crawler
- soup 路径下:BeautifulSoup4 与 Pandas
- backend 路径下:Django
- visualize 路径下:Matplotlib
Python 语法基础
Python入门与基础语法,见 Python 基础语法。
Python 进阶
Python Advanced Topics 文档主要分享一些 Python 的进阶内容,介绍一些实用技能栈。该文档涵盖 IPython 这一实用的 Python的交互式接口,以及 tqdm, argparse, pathlib 等实用 Python 库。
Numpy
Numpy(Numerical Python 的简称) 几乎是整个 Python 科学计算生态系统的核心,它提供了高效存储和操作密集数据缓存的接口。这部分文档介绍了 Numpy 的用法,尤其强调了以下重点内容:
- Numpy 和 Python 的效率区别
- Numpy 广播机制的规则
- Numpy Fancy Index
- 传统索引的视图问题
crawler
Crawler 文档主要讲述 Python 爬虫的基本用法以及实操建议,主要内容包括:
- 最基本的 HTTP 知识以及如何利用浏览器 inspect 功能;
- 解爬取网页的两大方式:利用 requests 发送请求,以及利用 selenium 模拟浏览器访问网页;
- 实际操作过程中的注意事项;
- 以不同类型的网页为例讲解什么情况下具体应当使用哪种方式。
BeautifulSoup4
BeautifulSoup4 可以帮助我们来处理请求获得的 HTML 页面中的数据,进行过滤、筛选、查找,是 Python 爬虫的重要工具。这部分文档以大量实例介绍了 BeautifulSoup4 的 API 和基本用法。
Pandas
Pandas 是在 NumPy 基础上建立的新程序库,提供了一种高效的 DataFrame 数据结构。DataFrame 本质上是一种带行标签和列标签、支持相同类型数据和缺失值的多维数组。Pandas 文档重点介绍该包中 Series、DataFrame 和其他相关数据结构的高效使用方法。
Django
Django 是一个由 Python 编写的一个开放源代码的 Web 应用框架。 使用 Django,只要很少的代码,Python 程序开发人员就可以轻松地完成一个正式网站所需要的大部分内容,并进一步开发出全功能的 Web 服务。
Django 部分教程旨在帮助大家:
- 了解如何使用 Django 开发一个简单应用程序;
- 了解前后端分离的开发模式,学习如何使用 Django 搭建一个后端;
- 掌握一种在服务器上部署 Django 的方式 (Django + Nginx + uWSGI 部署)。
Matplotlib
Matplotlib 是建立在 NumPy 数组基础上的多平台数据可视化程序库,这部分讲义将详细介绍使用 Python 的 Matplotlib 工具实现数据可视化的方法,涵盖线形图、散点图、直方图等,包含了大量实例。
额外注意
Pandas 与 Numpy 小学期并不必用,但是熟练的使用这两个工具会使得你的工作更加优雅。
下载
若要下载单个文件夹,复制该文件夹的网址,粘贴入 DownGit 中,选择 download 即可。
使用方法
文档全部由 markdown 与 Jupyter Notebook 写成。
Local Jupyter
你可以将仓库 clone 到本地使用,顺带练习你的 Git 技能,毕竟 QT 开发不使用 Git 会极度痛苦。同时,关于 Jupyter Notebook 和 Python 基础环境的配置请参考此链接。
Google Colab
你也可以使用 Google Colab 服务。
首先打开 Google Colab 为 Github 适配的界面。点击此链接,在对应位置输入该仓库链接:
texhttps://github.com/zhaochenyang20/Sino-Japanese-Relations-analysis然后 Enter,Colab 便会自动爬取该仓库的全部 ipynb 文件,并以列表形式显示在下面。点击对应文件右侧图标,便可以在新标签页打开该笔记本。
注意事项
由于 Colab 自带的包的版本都很低,可能会出现部分 API 不兼容的情况。所以在使用下列笔记本时,建议在运行前先进行包的安装和更新,创建一个新的代码框,在对应的笔记本下运行如下指令即可。
Numpy.ipynb
bash! pip install --upgrade numpyBeatifulSoup4.ipynb
bash! pip install --upgrade beautifulsoup4Pandas.ipynb
bash! pip install --upgrade pandas ! pip install --upgrade pandas-datareaderMatplotlib.ipynb
bash! pip install --upgrade matplotlib ! pip install --upgrade basemap ! pip install basemap-data-hires在安装和更新完毕后,Colab 会输出如下 log:
textWARNING: The following packages were previously imported in this runtime: [···] You must restart the runtime in order to use newly installed versions.此时需要点击 log 下方的
RESTART RUNTIME按钮即可将更新应用,接下来你便可以正常使用笔记本了。如果你发现有部分系统命令(即在 Jupyter Notebook 中以 ! 开头)无法运行,请尝试点击界面中的“复制到云端硬盘”,在 Google Drive 中的副本中运行。
学习顺序
建议小学期选择了 Python 的同学,按照基础语法,IPython,Crawler,BeautifulSoup4,Matplotlib,DJango 的顺序进行学习。而其余两块内容 Numpy,Pandas 在小学期使用并不多,可以留作个人兴趣衍生。
补充说明
由于时间仓促,错误在所难免,如若文档出现问题,请及时在本仓库的 Issue 界面提出。
为何而写
初起
暑假初期,我在处理暑培课程安排时,王导突然来找我,询问科协是否有课程指引方向的资料,类似 docs9 的风格。
一字班同学在问有没有零字班好哥哥好姐姐帮忙介绍介绍大一小学期,包括新雅那边他们也准备搞…
作为技能文档的参与者,我不得不说,技能文档的初衷本身即是希望大家收获课程之外的一些能力,能够在课程当中使用到,而并不是刻意针对课程的。比如暑假之后我们会更新 Numpy,Pandas,IPython 的内容,这些内容绝非课程必须,只是在课程作业中使用会让你的作业更加优雅有效。更何况,科协的一大初衷也是希望能够带大家认知到除了课业之外还有广阔的计算机科学与技术的天地,而绝非课程的一亩三分地。
因此,暑假结束前科协恕难提供这方面的支持,毕竟即便是暑培现有资料的整合,也需要有非常多后续的整理修改工作。为了打造臻于完美,服务后人的技能文档,网络部相关的同学们用心可谓良苦。
我只能回复王导,关于小学期的课程指南,可以参考计算机系的课程攻略文档。然而,类似 docs9 这类的文档,困难太大,恕难从命。
如此想来,这件事情的确与我无关。作为技能文档组的编写者与计算机系课咨委的一员,我尽到了我的责任。而且我已经度过了许多让我体验不佳的课程,按说这辈子我不可能再受这些课程的苦,下辈子我也不会再学计算机这专业。一切都与我无关,不妨如同大多数麻木的人一样,事不关己,高高挂起。
转折
然而,之后几天,我的良知却不免惴惴难安。
这真的是我渴望的生活吗?
参加课咨委的工作一整年了,我逐渐感知到,我之所以对于推动系内的课程改革有如此热忱,何尝不是不抱有薪火相传的初衷?
在我入学之前,就有杰哥等贵系的先辈们,积极地推动体系结构课程的改革,才能够让如今系内体系结构课程的体验有了大幅提升。之后,九字班学长学姐对小学期课程的提议和反馈得到了老师们的认可,才让零字班小学期压力控制在了合理的高压范围内,而非九字班所经历的魔鬼夏天。如果没有这些先辈学长学姐对于课改的探索,如果没有他们点亮了课改的火炬,我们现在又会经历怎样难堪的课程体验?
更何况,如果没有改革和参与改革的意识,每个人都安于现状,要么觉得事不关己高高挂起,要么觉得经历过的折磨一辈子不会有第二次,就选择对于任何意义的改革作壁上观,那么现在我们所生活的国家至今还是大清,绝非现在的中国。诚然我也激烈地批判着当下中国社会的种种弊病,然而我没谁也不愿意回到生产力落后,文化闭塞的清朝。社会改革促进了生产力的伟大进步,即便前人为了改革做出的牺牲已经让大多阅读到此处的人过上了衣食无忧的生活,然而我仍然坚信改革的火炬将会薪火相传。
于是乎,我再次想到了王导的问题。难道科协除了内容广泛的暑培外,暂时无法提供细致专业服务于小学期的指导,就不得不让同学们经历以往的前辈们在大一暑假曾经经历过的那些折磨吗?
绝不,至少我们还可以抱团自救。
星星之火,可以燎原。
虽然目前计算机系的部分课程质量仍然堪忧,但是我们每提出一次课改意见,每贡献一次开源资料,都会为计算机系课程质量提升留下不可磨灭的贡献。我们会帮助到之后的学弟学妹,更高年级学长学姐也会如此帮助我们。
尾声
于是乎,就有了你看到的此份文档。这份文档是我个人邀请三位一字班计算机系或者软院的同学们一同参考暑培讲义所编写的。基本涵盖了小学期 Python 课程的所有需求。在暑培课程之外,我们扩充了相应的文档和资料。从语法基础,到 IPython,Numpy,Pandas,BeautifulSoup4,Matplotlib,Django 等全部资料。
致谢
汇编者
暑培讲师
打工仔
大一小学期 Week 3 Python Docs Soup README (`大一小学期/Week_3-Python/docs/soup/README.md`)
FAQ
Q:我在运行部分代码时出现了一些异常,怎么办?
A:Pandas 库的更新很快,所以该文档具有一定的时效性。一切请以 Pandas 官方文档为准,或者使用搜索引擎搜索错误输出。
Q:使用 curl 指令下载示例所需的数据时,出现问题怎么办?
A:由于网络原因,可以考虑直接访问对应网站下载。如果数据确实已经下载,可以在 jupyter notebook 中使用 pwd 命令查看一下当前目录是否正确。
大一小学期 Week 3 Python Docs Visualize README (`大一小学期/Week_3-Python/docs/visualize/README.md`)
针对运行这份笔记中的代码时可能出现的一些问题,我们给出以下参考解决方案
需要使用 curl 指令下载 csv 格式数据文件来运行示例时,如果 curl 出现问题,可以直接向 pd.read_csv() 传入下载链接,直接从网络上加载数据;
在 Basemap 部分,如果遇到绘制的地图不符合预期的情况,可以尝试运行以下代码:
conda install -c conda-forge basemap-data-hires3.对于例子“Surface Temperature Data”,需要下载的数据文件较大,如果用curl指令下载过程中出现问题,可以尝试直接用浏览器访问美国宇航局戈达德太空研究所(NASA’s Goddard Institute for Space Studies)的网站,并下载所需数据文件至工作文件夹。
- 对于其它可能出现的异常情况,可以使用 Ipython 查阅 documents,自行调整 API 尝试解决。
大一小学期 Week 3 Python Docs CodeReview (`大一小学期/Week_3-Python/docs/CodeReview.md`)
审核者须知
参考技能文档的编写者须知,除此之外:
- 将翻译稿中出现的类似于“书中第 xx 章”的字样删去。
- 所以示例代码必须自己完全运行,避免因为 API 过于老旧无法使用。
重要事项
正确使用标点符号
- 正确使用全角标点符号与半角标点符号。汉语请使用全角符号,英语请使用半角符号。
- 请在每句话的末尾添加句号。
- 正确使用括号。括号在句中表示对句中前一个元素的解释说明,如
语法糖(英语:Syntactic sugar)。括号在句外表示对前面整个句子的解释说明。 - 正确使用分号,可以使得行文结构更加清晰。
正确进行中文排版
- 中英文之间、中文和数字之间需要增加空格,数字和单位之间不需要增加空格。
- 行文中正文与超链接之间需要增加空格。
- 全角字符和其他字符之间不加空格。
- 专有名词使用正确的大小写。如使用缩写,则该缩写应已成为业界标准。
推荐的代码风格
- 变量使用驼峰命名法、下划线命名法等均可,但需要尽量保证同一篇文档内命名风格统一。
- 下列代码风格惯例以 C++ 语言为例:
- 大括号换行与不换行均可,但需要保证同一篇文档内格式统一。不换行时,其与左侧的右括号之间应当有一个空格。
- 关键字
if、for等与后续左括号之间应当有一个空格。 - 运算符
+、-等与左右操作数之间应当各有一个空格,运算符.、->两侧均不应当有空格,逗号,左侧不应当有空格而右侧应当有空格。 - 行内注释起始标记
//与注释文字间应当有一个空格。 - 使用 2 个空格或者 4 个空格进行缩进均可,但需要保证同一篇文档内统一。
大一小学期 Week 3 Python Docs Backend Django (`大一小学期/Week_3-Python/docs/backend/Django.md`)
Django 与后端
Django 是一个由 Python 编写的一个开放源代码的 Web 应用框架。
使用 Django,只要很少的代码,Python 的程序开发人员就可以轻松地完成一个正式网站所需要的大部分内容,并进一步开发出全功能的 Web 服务。 Django 本身基于 MVC 模型,即 Model(模型)+ View(视图)+ Controller(控制器)设计模式,MVC 模式使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。
本教程旨在帮助大家入门 Django,并掌握一些后端开发的基本知识,具体来说,希望帮助大家达成以下目标:
- 了解如何使用 Django 开发一个简单应用程序;
- 了解前后端分离的开发模式,学习如何使用 Django 搭建一个后端;
- 掌握一种在服务器上部署 Django 的方式 (Django + Nginx + uWSGI 部署)。
前置准备
请参考 lambda 学长暑培授课中的课前准备文档。
通过此命令可以检查你是否已经安装 Django 及 Django 版本。
python -m django --version创建一个简单的投票应用
新建项目
如果这是你第一次使用 Django 的话,你需要一些初始化设置。也就是说,你需要用一些自动生成的代码配置一个 Django project —— 即一个 Django 项目实例需要的设置项集合,包括数据库配置、Django 配置和应用程序配置。
打开命令行,cd 到一个你想放置你代码的目录,然后运行以下命令:
django-admin startproject mysite这行代码将会在当前目录下创建一个 mysite 目录。在其中,你会看到以下文件树:
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py这些目录和文件的用处是:
- 最外层的
mysite/根目录只是你项目的容器, 根目录名称对 Django 没有影响,你可以将它重命名为任何你喜欢的名称。 manage.py: 一个让你用各种方式管理 Django 项目的命令行工具。许多如运行临时服务器、生成 migration, 迁移数据库结构等操作都可以通过manage.py进行。我们也可以在manage.py中运行自定义命令。- 里面一层的
mysite/目录包含你的项目,它是一个纯 Python 包。它的名字就是当你引用它内部任何东西时需要用到的 Python 包名。 (比如mysite.urls). mysite/__init__.py:一个空文件,告诉 Python 这个目录应该被认为是一个 Python 包。mysite/settings.py:Django 项目的配置文件。mysite/urls.py:Django 项目的 URL 声明,就像你网站的“目录”。mysite/asgi.py:作为你的项目的运行在 ASGI 兼容的 Web 服务器上的入口。mysite/wsgi.py:作为你的项目的运行在 WSGI 兼容的 Web 服务器上的入口。
简易服务器
在 mysite 目录下,运行以下代码:
python manage.py runserver即可启动一个临时服务器(只能用于开发测试,而不应当用于生产环境)。通过浏览器访问 http://127.0.0.1:8000/ (Djaongo 默认监听 127.0.0.1:8000)你将看到一个“祝贺”页面,证明你已经成功创建了项目。这个简易服务器之后可用于开发中的测试。
新建应用
应用和项目是多对多的关系。一个应用通常用于完成一个相对独立的功能,可以安装于不同的项目中; 而一个项目也可以包含多个应用。
下面我们来演示创建应用:
python manage.py startapp <app_name>例如,在manage.py所在目录下运行以下代码:
python manage.py startapp polls将创建一个名为 polls 的应用。
在 Django 中,每一个应用都是一个 Python 包,并且遵循着相同的约定。Django 自带一个工具,可以帮你生成应用的基础目录结构。例如,你可以观察一下刚刚创建的投票应用的文件目录。
创建视图
视图可以根据不同的请求给出 HTTP 响应,我们来为 polls 创建个简单的视图。例如我们在 polls/views.py 中输入:
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the polls index.")这时,调用 index 将返回一个 HTTP 响应,内容为 Hello, world. You're at the polls index. 。
创建路由
路由配置告诉 Django 哪些的 URL 应该被分配给哪些视图。我们来为我们刚才编写的 index 试图配置路由。
首先配置应用一级的路由,在 polls 目录下新建 urls.py ,输入以下内容:
from django.urls import path
from . import views
urlpatterns = [
path('hello', views.index, name='index'),
]然后配置项目一级的路由:
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls'))
]这里需要注意 include 函数可以引用其他位置的 URL 配置,并将截断匹配的部分,将剩余部分分发给后续的 URL 配置进行匹配。
这时我们运行临时服务器测试访问这个页面:
python manage.py runserver访问
http://localhost:8000/polls/hello预期观察到的响应为 Hello, world. You're at the polls index.
我们回过头来看看我们的请求是如何被分配到 index 的。
当我们访问 http://localhost:8000/polls/hello ,Django 哪来进行匹配的部分是 polls/hello 首先在项目一级匹配,匹配到了 polls/ ,于是 polls/ 被去除,剩下 hello 子串到应用 polls 的 urls.py 中进行匹配。hello 子串又匹配到了视图 index 。此时 HTTP 请求作为第一个参数传给了 index 函数进行处理。index 函数处理这个请求后,应当返回一个 HttpResponse 对象,Django 会将这个对象对应的 HTTP 响应传递给客户端。
使用数据库
接下来我们来演示如何使用 Django 的 ORM 模型来操作数据库。Django 支持多种数据库。默认情况下,Django使用 SQLite3 作为数据库。这种情形无需配置。我们也可以使用 MySQL 作为数据库。在此处我们以 MySQL 为例。如果你对 MySQL 不熟悉,可以参看暑培文档中的 MySQL 部分。
settings.py
在使用数据库前,我们需要先了解 settings.py 中进行一些常用设置:
DEBUG
决定项目是在调试状态还是在生产环境。
永远不要在 DEBUG 开启的情况下将网站部署到生产中。DEBUG 开启时,产生错误会返回详细的错误报告,其中包含许多敏感信息,不宜在生产环境中泄露。DEBUG 关闭时,产生的错误仅有简略说明。
ALLOWED_HOSTS
允许访问的域名列表,其他域名访问将直接被 ban,响应为 HTTP 400.
INSTALLED_APPS
表示该项目使用了哪些应用。Django会为在其中列出的应用进行注册。会进行启动配置、跟踪 migration 等数据库信息。
DATABASES
表示使用何种数据库,以及使用数据库时的配置,如主机、端口、用户名密码等等。
配置 MySQL 数据库
下面按照 Django 文档中的示例,演示为项目配置 MySQL 数据库。
首先安装 mysqlclient:
pip install mysqlclient然后在恰当位置创建 MySQL 数据库的配置文件 my.cnf ,输入你的数据库配置:
[client]
host = 服务器地址
database = 所选数据库
user = 用户名
password = 密码
port = 端口
default-character-set = 字符集,这里推荐 utf8mb4然后,在 settings.py 进行如下修改:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'read_default_file': '<my.cnf 的地址>',
},
}
}如果填入的地址为相对路径,那么将会是相对运行 manage.py 时的工作目录。
建立模型
模型对应于数据库中的表,可以用来设计和访问数据库的结构。我们为 polls 应用建立模型。编辑 models.py 输入以下内容:
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.FloatField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)上面的代码建立了两个模型,对应于数据库中的两张表。模型是 models.Model 的子类,模型的字段是 models.Field 的实例。模型的每个字段对应于数据库中的一个字段。
在建立模型后我们需要让 Django 在数据库中建立这些模型,或对模型的修改做出对应数据库结构的调整。因此我们需要首先注册这一应用。在 settings.py 中,将我们的应用添加到 INSTALLED_APPS 中。
INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]这时应用 polls 就被添加到了我们的 Django 项目中了。
我们运行:
python manage.py makemigrations polls
Migrations for 'polls':
polls\migrations\0001_initial.py
- Create model Question
- Create model Choice此时 Django 会检测我们对应用 polls 的模型做了哪些修改,在将这些修改操作汇总到一个 Python 文 件中。
我们可以看到在 polls/migrations 目录中出现了一个 0001_initial.py 文件。我们通常无需阅读 migrations 中的文件。
接下来我们需要将修改操作应用到数据库:
python manage.py migrate此时你对模型的修改将会被执行到数据库中。注意到修改包含了大量其他模型的操作,这是因为我们在 INSTALLED_APPS 中配置了许多应用,而这些应用的模型尚未建立。
对于应用更改时具体执行的 SQL 语句,我们可以使用:
python manage.py sqlmigrate polls 0001来查看 migration 0001 对应的 SQL 语句。
从这些语句中我们发现 Django 默认为我们建立主键,并添加了外键约束。
**总结起来,修改模型并应用修改分为 3 步: **
- 编辑
models.py文件,改变模型。 - 运行
python manage.py makemigrations为模型的改变生成迁移文件。 - 运行
python manage.py migrate来应用数据库迁移。
一些常见的模型定义:
以下面这段代码为例展示一些模型构建的常用内容:
# 创建枚举选项:
class Role(models.TextChoices):
MEMBER = "member"
DEV = "dev"
QA = "qa"
SYS = "sys"
SUPERMASTER = "supermaster"
class PendingModifyPasswordEmail(models.Model):
# 指定主键
id = models.BigAutoField(primary_key=True)
# 唯一
hash1 = models.CharField(max_length=100, unique=True)
# 枚举类型
role = models.CharField(max_length=12, choices=Role.choices)
# 默认函数
createdAt = models.FloatField(default=getTime.get_timestamp)
class Meta:
# 索引
indexes = [
models.Index(fields=["hash1", "role"]),
models.Index(fields=["createdAt"]),
]
# 联合唯一
unique_together = ["hash1", "createdAt"]模型 API
我们可以利用模型 API 完成对数据的操作。下面我们在 Django Shell 中演示一些常见模型 API 的使用方法。当然,我们通常会在视图函数中使用这些 API,使用交互式方式只是为了便于演示。
首先启动 Django Shell:
python manage.py shell在 Django Shell 中:
/* Detailed source-code truncated for AI context efficiency. */在这里我们发现对象的显示不太方便,我们可以配置相应模型的 __str__ 方法来自定义模型的显示内容:
为 Question 和 Choice 分别定义以下方法即可:
def __str__(self):
return f"{self.question_text} @ {self.pub_date}"def __str__(self):
return f"{self.choice_text} [{self.votes}]"然后重启 Django Shell,再次尝试查询:
>>> from polls.models import *
# 自定义显示:
>>> Choice.objects.all()
<QuerySet [<Choice: A [0]>, <Choice: B [0]>, <Choice: C [0]>]>
>>> Question.objects.all()
<QuerySet [<Question: Is it a question? @ 1658422997.1246326>,
<Question: Is it a question? @ 1658423046.8407936>,
<Question: Is it another question? @ 1658423054.8635635>]>接下来我们看看如何修改对象。和创建类似地,有两种方法:
# save object: 修改特定对象
>>> ch = Choice.objects.get(pk=2) >>> ch.votes = 114514
>>> ch.save()
# update: 修改整个 Query Set
>>> Choice.objects.filter(id=3).update(votes=255) 1
# 查看修改效果
>>> Choice.objects.all()
<QuerySet [<Choice: A [0]>, <Choice: B [114514]>, <Choice: C [255]>]>然后是一些基本的查询方法(注意使用双下划线进行级联的写法):
/* Detailed source-code truncated for AI context efficiency. */我们可以使用 .query 来查看 QuerySet 对应的 SQL 语句:
>>> print(
... Choice.objects.filter(
... Q(question__id=2) & (~Q(choice_text__in=["A", "B"]) | Q(id=1))
... ).query
... )
SELECT `polls_choice`.`id`, `polls_choice`.`question_id`, `polls_choice`.`choice_text`, `polls_choice`.`votes` FROM `polls_choice` WHERE(`polls_choice`.`question_id` = 2 AND (NOT (`polls_choice`.`choice_text` IN (A, B)) OR `polls_choice`.`id` = 1))在查询复杂(或者开发者对 ORM 接口不熟悉)的情况下也可以直接裸写 SQL。由于不同 SQL 实现的版 本的差异,这样的代码并不想 ORM 那样具有较为良好的迁移性。
>>> Choice.objects.raw("SELECT * FROM ...")当然,并不是说如果使用 ORM 就一定能保证代码在不同数据库之间无损转换。例如 Postgre SQL 的 DISTINCT ON 接口就会导致一部分代码迁移到 MySQL 后不能使用。而如果要把一部分数据从一种数据 库迁移到另一种数据库,这通常也十分令人头大。
这里介绍了创建应用程序的基本方法,如果想要体验创建一个完整应用程序的过程,请参看文档
前后端分离的开发模式
对于 Web 应用来说,可以将其简单视为 2 部分:
- 前端:用户可以看到并与之交互的部分。
- 后端:用户看不到,但承担着一些如数据存储、计算等等功能的部分。
对于前后端的互动,也可以简单分成两种模式: - 服务端渲染:服务端将用户看到的界面计算好,然后整体以 HTML 的形式返回。
- 用户端渲染:服务端先将不含数据,但包含交互逻辑的前端传给客户端。客户端需要时向服务端请求数据,利用请求的数据来完成页面的渲染。
对于当前日趋复杂的 Web 应用来说,前后端分离的是一种日趋流行的趋势
- 前后端分离应用的页面在交互的过程中,只传递了数据,而不是渲染好的整个视图,更加高效、灵活。
- 后端人员与前端人员的工作解耦,两者只需要通过约定的 API 进行协作,不需要代码的直接交互,不会出现后端开发里面嵌入了前端代码这种难以维护情形。
可能还需要说明的是,在学会前后端分离后,并不一定所有的任务都一定要上前后端分离,有些非常简单的任务用耦合的架构大概就能做的非常好了。
Templates & Forms
Django 对前后端耦合的开发模式有深入的支持,但模板和表单在前后端分离的开发中使用较少,不是本节的重点,在这里附上文档链接,供有兴趣的同学查阅。
- 模板:https://docs.djangoproject.com/zh-hans/4.0/intro/tutorial03/
- 表单:Generic View:https://docs.djangoproject.com/zh-hans/4.0/intro/tutorial04/
以下介绍使用 Djaongo 搭建纯后端的基本操作。
使用 Django 收发请求
作为一个后端来说,最为常规的操作可能读取请求参数和收发各种 JSON。
GET
仍以上述投票程序为例,假设我们希望实现这样一个接口,请求 /polls/questions/ 返回 id=2 的问题文本、创建时间和所有选项,此时我们可以写如下一个视图函数:
from django.http import HttpRequest, JsonResponse
from .models import *
from django.forms.models import model_to_dict
def question_detail(req: HttpRequest, qid: int):
res = Question.objects.filter(id=qid).first()
if res:
return JsonResponse({
"code": 0,
"data": {
**model_to_dict(res),
"choices": [
model_to_dict(ch, exclude=["question"])
for ch in res.choice_set.all()
]
}
})
else:
return JsonResponse({
"code": -1
}, status=404)其接受一个 HttpRequest 对象和被查询问题的 id ,使用 model_to_dict 将问题对象转换为 dict , 再将问题对应所有的 Choice 转化也都转化为 dict 。最后将这个 dict 与 list 的复合物封装成 JSON 返回。
然后我们在 polls/urls.py 中为其配置路由。
from django.urls import path
from . import views
urlpatterns = [
path('question/<int:qid>', views.question_detail),
]这里我们遇到一种新的路由格式。其在匹配到这一项后相当于调用了:
views.question_detail(request=<HttpRequest object>, qid=<int:qid>)qid 被作为关键字参数传给了 views.question_detail。
更多 URL Pattern 写法详见官方文档。
这时我们可以使用 Postman 对该接口进行验证和调试。
此外,对于 GET 请求中附带的参数,可以使用 req.GET 获取,例如添加上 print(req.GET) 即可获取 GET 请求的参数。
POST
我们考虑另一种情形,就是给指定问题的指定选项投票,类似于以下场景:
// 请求
{
"qid": 2,
"cid": 0
}
// 响应
{
"code": 0,
"choices": [...]
}这时我们可以撰写类似这样的一个视图函数:
def vote(req: HttpRequest):
info = json.loads(req.body)
try:
qid = info["qid"]
cid = info["cid"]
ch = Choice.objects.get(pk=cid)
if ch.question.id != qid:
raise ValueError("Mismatched question and choice pair")
ch.votes += 1
ch.save()
return JsonResponse({
"code": 0,
"choices": [
model_to_dict(ch, exclude=["question"])
for ch in Choice.objects.filter(question__id=qid)
]
})
except:
if settings.DEBUG:
raise
return JsonResponse({
"code": -1
}, status=400)然后添加一条路由:
path('vote', views.vote)这时在 Postman 中查询,发现响应为 HTTP 403,原因是缺少 CSRF token(出于安全性考虑,Djaongo 默认要求 POST 请求携带 CSRF token,已表明该请求来自被授权的表单)。
在这里我们不妨直接添加装饰器关闭 CSRF token 检查。
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def vote(req: HttpRequest):
...有时我们希望指定请求的方法,可以使用:
from django.views.decorators.http import require_http_methods as method
@method(["GET"])
def leaderboard(req: HttpRequest):
...此时若收到的请求不是 GET 请求,则会返回一个错误。
部署 Django
后端编写好后,我们希望将其部署在服务器上,这样我们就可以通过服务器对外网的端口访问页面。
在此使用一种典型部署:使用 uWSGI 来代理 Django,再用反向代理 Nginx 连接 uWSGI,将其代理到外网。
uWSGI
现在我们准备将 Django 部署到服务器上了。
先将文件转移到服务器的某个文件夹中(如果你使用 PyCharm,则可以使用其内置的“部署”工具来进行转移),这里以暑培服务器为例,选择 /home/train/site。
在前置准备中,我们已经安装了 conda 并配置好了虚拟环境,确认了 Nginx 可以正常启动。
进入网站目录,启动虚拟环境,用以下代码,我们可以将 uWSGI 代理到 10001 端口:
uwsgi --http :10001 --module mysite.wsgi其中 module 参数指出相应的 Python 模块。
现在我们就可以从外网通过端口来访问这个 Django 应用了。
如果提示无法连接到 MySQL 服务器,则可在 mysite/__init__.py 中加入以下代码:
import pymysql
pymysql.install_as_MySQLdb()我们也可以使用配置文件来进行操作:
[uwsgi]
socket = :9999
chdir = /home/train/site module = mysite.wsgi master = true
processes = 9
threads = 9
vacuum = true然后
uwsgi --ini u.ini其中,如果直接使用 uWSGI 应该指定 http,否则指定 socket。
关于 Django + uWSGI 的更多配置,详见如何用 uWSGI 托管 Django。
Nginx
我们可以先来个极简配置,代理一波 uWSGI(更细致的配置可以参考其官方文档)。
在 /etc/nginx/sites-enabled/default 中加入以下内容:
(uWSGI 将 Django 代理到了 127.0.0.1 的 9999 端口,Nginx 又将其代理到了 10002 端口)
server{
listen 10002;
server_name 59.66.131.240;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:9999;
uwsgi_read_timeout 15;
}
}此时在命令行中执行:
sudo service nginx start此时就可以在外网中访问之前搭建的网页了。
另外也可以使用 Nginx 配置静态文件的代理。形如:
server {
listen 10001;
server_name 59.66.131.240;
location / {
root /home/nana/build;
index index.html;
}有时我们会遇到 Nginx 没有权限读取内容的问题,表现为 HTTP 403,此时可以给相关文件加上权限, chown,甚至可以直接找到 /etc/nginx/nginx.conf ,将其首部的 user 改为 root。
查找错误
在配置 Nginx 时,常用
sudo nginx -t
sudo cat /var/log/nginx/error.log定位错误(前者检查配置文件中的错误,后者展示错误日志)。
例如配置文件编写有误,或端口被占用等问题,就可以被这两个命令发现。
扩展阅读
还有一些比较常用的主题,篇幅有限,以下是链接:
单元测试 UnitTest: https://docs.djangoproject.com/zh-hans/4.0/intro/tutorial05/
Middle Ware: https://docs.djangoproject.com/zh-hans/4.0/topics/http/middleware/
Command: https://docs.djangoproject.com/zh-hans/4.0/howto/custom-management-comm ands/
Django REST Framework:https://www.django-rest-framework.org
大一小学期 Week 3 Python Exam 2016 Docs Contents (`大一小学期/Week_3-Python/exam/2016/docs/contents.txt`)
============================= Django documentation contents
.. toctree::
:hidden:
index.. toctree::
:maxdepth: 3
intro/index
topics/index
howto/index
faq/index
ref/index
misc/index
glossary
releases/index
internals/indexIndices, glossary and tables
- :ref:
genindex - :ref:
modindex - :doc:
glossary
大一小学期 Week 3 Python Exam 2016 Docs Glossary (`大一小学期/Week_3-Python/exam/2016/docs/glossary.txt`)
======== Glossary
.. glossary::
concrete model
A non-abstract (:attr:`abstract=False
<django.db.models.Options.abstract>`) model.
field
An attribute on a :term:`model`; a given field usually maps directly to
a single database column.
See :doc:`/topics/db/models`.
generic view
A higher-order :term:`view` function that provides an abstract/generic
implementation of a common idiom or pattern found in view development.
See :doc:`/topics/class-based-views/index`.
model
Models store your application's data.
See :doc:`/topics/db/models`.
MTV
"Model-template-view"; a software pattern, similar in style to MVC, but
a better description of the way Django does things.
See :ref:`the FAQ entry <faq-mtv>`.
MVC
`Model-view-controller`__; a software pattern. Django :ref:`follows MVC
to some extent <faq-mtv>`.
__ https://en.wikipedia.org/wiki/Model-view-controller
project
A Python package -- i.e. a directory of code -- that contains all the
settings for an instance of Django. This would include database
configuration, Django-specific options and application-specific
settings.
property
Also known as "managed attributes", and a feature of Python since
version 2.2. This is a neat way to implement attributes whose usage
resembles attribute access, but whose implementation uses method calls.
See :class:`property`.
queryset
An object representing some set of rows to be fetched from the database.
See :doc:`/topics/db/queries`.
slug
A short label for something, containing only letters, numbers,
underscores or hyphens. They're generally used in URLs. For
example, in a typical blog entry URL:
.. parsed-literal::
https://www.djangoproject.com/weblog/2008/apr/12/**spring**/
the last bit (``spring``) is the slug.
template
A chunk of text that acts as formatting for representing data. A
template helps to abstract the presentation of data from the data
itself.
See :doc:`/topics/templates`.
view
A function responsible for rendering a page.大一小学期 Week 3 Python Exam 2016 Docs Index (`大一小学期/Week_3-Python/exam/2016/docs/index.txt`)
==================== Django documentation
.. rubric:: Everything you need to know about Django.
Getting help
Having trouble? We'd like to help!
Try the :doc:
FAQ <faq/index>-- it's got answers to many common questions.Looking for specific information? Try the :ref:
genindex, :ref:modindexor
the :doc:detailed table of contents <contents>.Search for information in the archives of the |django-users| mailing list, or
post a question_.Ask a question in the
#django IRC channel, or search theIRC logsto see
if it's been asked before.Report bugs with Django in our
ticket tracker_.
.. _archives: https://groups.google.com/group/django-users/
.. _post a question: https://groups.google.com/d/forum/django-users
.. _#django IRC channel: irc://irc.freenode.net/django
.. _IRC logs: http://django-irc-logs.com/
.. _ticket tracker: https://code.djangoproject.com/
How the documentation is organized
Django has a lot of documentation. A high-level overview of how it's organized
will help you know where to look for certain things:
:doc:
Tutorialstake you by the hand through a series of
steps to create a Web application. Start here if you're new to Django or Web
application development. Also look at the ":ref:index-first-steps" below.:doc:
Topic guides </topics/index>discuss key topics and concepts at a
fairly high level and provide useful background information and explanation.:doc:
Reference guides </ref/index>contain technical reference for APIs and
other aspects of Django's machinery. They describe how it works and how to
use it but assume that you have a basic understanding of key concepts.:doc:
How-to guides </howto/index>are recipes. They guide you through the
steps involved in addressing key problems and use-cases. They are more
advanced than tutorials and assume some knowledge of how Django works.
.. _index-first-steps:
First steps
Are you new to Django or to programming? This is the place to start!
From scratch:
:doc:Overview|
:doc:InstallationTutorial:
:doc:Part 1: Requests and responses|
:doc:Part 2: Models and the admin site|
:doc:Part 3: Views and templates|
:doc:Part 4: Forms and generic views|
:doc:Part 5: Testing|
:doc:Part 6: Static files|
:doc:Part 7: Customizing the admin siteAdvanced Tutorials:
:doc:How to write reusable apps|
:doc:Writing your first patch for Django
The model layer
Django provides an abstraction layer (the "models") for structuring and
manipulating the data of your Web application. Learn more about it below:
Models:
:doc:Introduction to models <topics/db/models>|
:doc:Field types <ref/models/fields>|
:doc:Meta options <ref/models/options>|
:doc:Model class <ref/models/class>QuerySets:
:doc:Executing queries <topics/db/queries>|
:doc:QuerySet method reference <ref/models/querysets>|
:doc:Lookup expressions <ref/models/lookups>Model instances:
:doc:Instance methods <ref/models/instances>|
:doc:Accessing related objects <ref/models/relations>Migrations:
:doc:Introduction to Migrations<topics/migrations>|
:doc:Operations reference <ref/migration-operations>|
:doc:SchemaEditor <ref/schema-editor>|
:doc:Writing migrations <howto/writing-migrations>Advanced:
:doc:Managers <topics/db/managers>|
:doc:Raw SQL <topics/db/sql>|
:doc:Transactions <topics/db/transactions>|
:doc:Aggregation <topics/db/aggregation>|
:doc:Search <topics/db/search>|
:doc:Custom fields <howto/custom-model-fields>|
:doc:Multiple databases <topics/db/multi-db>|
:doc:Custom lookups <howto/custom-lookups>|
:doc:Query Expressions <ref/models/expressions>|
:doc:Conditional Expressions <ref/models/conditional-expressions>|
:doc:Database Functions <ref/models/database-functions>Other:
:doc:Supported databases <ref/databases>|
:doc:Legacy databases <howto/legacy-databases>|
:doc:Providing initial data <howto/initial-data>|
:doc:Optimize database access <topics/db/optimization>|
:doc:PostgreSQL specific features <ref/contrib/postgres/index>
The view layer
Django has the concept of "views" to encapsulate the logic responsible for
processing a user's request and for returning the response. Find all you need
to know about views via the links below:
The basics:
:doc:URLconfs <topics/http/urls>|
:doc:View functions <topics/http/views>|
:doc:Shortcuts <topics/http/shortcuts>|
:doc:Decorators <topics/http/decorators>Reference:
:doc:Built-in Views <ref/views>|
:doc:Request/response objects <ref/request-response>|
:doc:TemplateResponse objects <ref/template-response>File uploads:
:doc:Overview <topics/http/file-uploads>|
:doc:File objects <ref/files/file>|
:doc:Storage API <ref/files/storage>|
:doc:Managing files <topics/files>|
:doc:Custom storage <howto/custom-file-storage>Class-based views:
:doc:Overview <topics/class-based-views/index>|
:doc:Built-in display views <topics/class-based-views/generic-display>|
:doc:Built-in editing views <topics/class-based-views/generic-editing>|
:doc:Using mixins <topics/class-based-views/mixins>|
:doc:API reference <ref/class-based-views/index>|
:doc:Flattened index<ref/class-based-views/flattened-index>Advanced:
:doc:Generating CSV <howto/outputting-csv>|
:doc:Generating PDF <howto/outputting-pdf>Middleware:
:doc:Overview <topics/http/middleware>|
:doc:Built-in middleware classes <ref/middleware>
The template layer
The template layer provides a designer-friendly syntax for rendering the
information to be presented to the user. Learn how this syntax can be used by
designers and how it can be extended by programmers:
The basics:
:doc:Overview <topics/templates>For designers:
:doc:Language overview <ref/templates/language>|
:doc:Built-in tags and filters <ref/templates/builtins>|
:doc:Humanization <ref/contrib/humanize>For programmers:
:doc:Template API <ref/templates/api>|
:doc:Custom tags and filters <howto/custom-template-tags>
Forms
Django provides a rich framework to facilitate the creation of forms and the
manipulation of form data.
The basics:
:doc:Overview <topics/forms/index>|
:doc:Form API <ref/forms/api>|
:doc:Built-in fields <ref/forms/fields>|
:doc:Built-in widgets <ref/forms/widgets>Advanced:
:doc:Forms for models <topics/forms/modelforms>|
:doc:Integrating media <topics/forms/media>|
:doc:Formsets <topics/forms/formsets>|
:doc:Customizing validation <ref/forms/validation>
The development process
Learn about the various components and tools to help you in the development and
testing of Django applications:
Settings:
:doc:Overview <topics/settings>|
:doc:Full list of settings <ref/settings>Applications:
:doc:Overview <ref/applications>Exceptions:
:doc:Overview <ref/exceptions>django-admin and manage.py:
:doc:Overview <ref/django-admin>|
:doc:Adding custom commands <howto/custom-management-commands>Testing:
:doc:Introduction <topics/testing/index>|
:doc:Writing and running tests <topics/testing/overview>|
:doc:Included testing tools <topics/testing/tools>|
:doc:Advanced topics <topics/testing/advanced>Deployment:
:doc:Overview <howto/deployment/index>|
:doc:WSGI servers <howto/deployment/wsgi/index>|
:doc:Deploying static files <howto/static-files/deployment>|
:doc:Tracking code errors by email <howto/error-reporting>
The admin
Find all you need to know about the automated admin interface, one of Django's
most popular features:
- :doc:
Admin site <ref/contrib/admin/index> - :doc:
Admin actions <ref/contrib/admin/actions> - :doc:
Admin documentation generator<ref/contrib/admin/admindocs>
Security
Security is a topic of paramount importance in the development of Web
applications and Django provides multiple protection tools and mechanisms:
- :doc:
Security overview <topics/security> - :doc:
Disclosed security issues in Django <releases/security> - :doc:
Clickjacking protection <ref/clickjacking> - :doc:
Cross Site Request Forgery protection <ref/csrf> - :doc:
Cryptographic signing <topics/signing> - :ref:
Security Middleware <security-middleware>
Internationalization and localization
Django offers a robust internationalization and localization framework to
assist you in the development of applications for multiple languages and world
regions:
- :doc:
Overview <topics/i18n/index>|
:doc:Internationalization <topics/i18n/translation>|
:ref:Localization <how-to-create-language-files>|
:doc:Localized Web UI formatting and form input <topics/i18n/formatting> - :doc:
Time zones </topics/i18n/timezones>
Performance and optimization
There are a variety of techniques and tools that can help get your code running
more efficiently - faster, and using fewer system resources.
- :doc:
Performance and optimization overview <topics/performance>
Python compatibility
Django aims to be compatible with multiple different flavors and versions of
Python:
- :doc:
Jython support <howto/jython> - :doc:
Python 3 compatibility <topics/python3>
Geographic framework
:doc:GeoDjango <ref/contrib/gis/index> intends to be a world-class geographic
Web framework. Its goal is to make it as easy as possible to build GIS Web
applications and harness the power of spatially enabled data.
Common Web application tools
Django offers multiple tools commonly needed in the development of Web
applications:
- Authentication:
:doc:Overview <topics/auth/index>|
:doc:Using the authentication system <topics/auth/default>|
:doc:Password management <topics/auth/passwords>|
:doc:Customizing authentication <topics/auth/customizing>|
:doc:API Reference <ref/contrib/auth> - :doc:
Caching <topics/cache> - :doc:
Logging <topics/logging> - :doc:
Sending emails <topics/email> - :doc:
Syndication feeds (RSS/Atom) <ref/contrib/syndication> - :doc:
Pagination <topics/pagination> - :doc:
Messages framework <ref/contrib/messages> - :doc:
Serialization <topics/serialization> - :doc:
Sessions <topics/http/sessions> - :doc:
Sitemaps <ref/contrib/sitemaps> - :doc:
Static files management <ref/contrib/staticfiles> - :doc:
Data validation <ref/validators>
Other core functionalities
Learn about some other core functionalities of the Django framework:
- :doc:
Conditional content processing <topics/conditional-view-processing> - :doc:
Content types and generic relations <ref/contrib/contenttypes> - :doc:
Flatpages <ref/contrib/flatpages> - :doc:
Redirects <ref/contrib/redirects> - :doc:
Signals <topics/signals> - :doc:
System check framework <topics/checks> - :doc:
The sites framework <ref/contrib/sites> - :doc:
Unicode in Django <ref/unicode>
The Django open-source project
Learn about the development process for the Django project itself and about how
you can contribute:
Community:
:doc:How to get involved|
:doc:The release process|
:doc:Team organization|
:doc:Meet the team|
:doc:Current roles|
:doc:The Django source code repository|
:doc:Security policies|
:doc:Mailing listsDesign philosophies:
:doc:Overview <misc/design-philosophies>Documentation:
:doc:About this documentationThird-party distributions:
:doc:Overview <misc/distributions>Django over time:
:doc:API stability <misc/api-stability>|
:doc:Release notes and upgrading instructions <releases/index>|
:doc:Deprecation Timeline
大一小学期 Week 3 Python Exam 2016 Docs Faq Admin (`大一小学期/Week_3-Python/exam/2016/docs/faq/admin.txt`)
============== FAQ: The admin
I can't log in. When I enter a valid username and password, it just brings up the login page again, with no error messages.
The login cookie isn't being set correctly, because the domain of the cookie
sent out by Django doesn't match the domain in your browser. Try setting the
:setting:SESSION_COOKIE_DOMAIN setting to match your domain. For example, if
you're going to "https://www.example.com/admin/" in your browser, setSESSION_COOKIE_DOMAIN = 'www.example.com'.
I can't log in. When I enter a valid username and password, it brings up the login page again, with a "Please enter a correct username and password" error.
If you're sure your username and password are correct, make sure your user
account has :attr:~django.contrib.auth.models.User.is_active and
:attr:~django.contrib.auth.models.User.is_staff set to True. The admin site
only allows access to users with those two fields both set to True.
How do I automatically set a field's value to the user who last edited the object in the admin?
The :class:~django.contrib.admin.ModelAdmin class provides customization hooks
that allow you to transform an object as it saved, using details from the
request. By extracting the current user from the request, and customizing the
:meth:~django.contrib.admin.ModelAdmin.save_model hook, you can update an
object to reflect the user that edited it. See :ref:the documentation on ModelAdmin methods <model-admin-methods> for an example.
How do I limit admin access so that objects can only be edited by the users who created them?
The :class:~django.contrib.admin.ModelAdmin class also provides customization
hooks that allow you to control the visibility and editability of objects in the
admin. Using the same trick of extracting the user from the request, the
:meth:~django.contrib.admin.ModelAdmin.get_queryset and
:meth:~django.contrib.admin.ModelAdmin.has_change_permission can be used to
control the visibility and editability of objects in the admin.
My admin-site CSS and images showed up fine using the development server, but they're not displaying when using mod_wsgi.
See :ref:serving the admin files <serving-the-admin-files>
in the "How to use Django with mod_wsgi" documentation.
My "list_filter" contains a ManyToManyField, but the filter doesn't display.
Django won't bother displaying the filter for a ManyToManyField if there
are fewer than two related objects.
For example, if your :attr:~django.contrib.admin.ModelAdmin.list_filter
includes :doc:sites </ref/contrib/sites>, and there's only one site in your
database, it won't display a "Site" filter. In that case, filtering by site
would be meaningless.
Some objects aren't appearing in the admin.
Inconsistent row counts may be caused by missing foreign key values or a
foreign key field incorrectly set to :attr:null=False <django.db.models.Field.null>. If you have a record with a
:class:~django.db.models.ForeignKey pointing to a non-existent object and
that foreign key is included is
:attr:~django.contrib.admin.ModelAdmin.list_display, the record will not be
shown in the admin changelist because the Django model is declaring an
integrity constraint that is not implemented at the database level.
How can I customize the functionality of the admin interface?
You've got several options. If you want to piggyback on top of an add/change
form that Django automatically generates, you can attach arbitrary JavaScript
modules to the page via the model's class Admin :ref:js parameter <modeladmin-asset-definitions>. That parameter is a list of URLs, as strings,
pointing to JavaScript modules that will be included within the admin form via
a <script> tag.
If you want more flexibility than simply tweaking the auto-generated forms,
feel free to write custom views for the admin. The admin is powered by Django
itself, and you can write custom views that hook into the authentication
system, check permissions and do whatever else they need to do.
If you want to customize the look-and-feel of the admin interface, read the
next question.
The dynamically-generated admin site is ugly! How can I change it?
We like it, but if you don't agree, you can modify the admin site's
presentation by editing the CSS stylesheet and/or associated image files. The
site is built using semantic HTML and plenty of CSS hooks, so any changes you'd
like to make should be possible by editing the stylesheet.
What browsers are supported for using the admin?
The admin provides a fully-functional experience to YUI's A-grade_ browsers,
with the notable exception of IE6, which is not supported.
There may be minor stylistic differences between supported browsers—for
example, some browsers may not support rounded corners. These are considered
acceptable variations in rendering.
.. _YUI's A-grade: https://github.com/yui/yui3/wiki/Graded-Browser-Support
大一小学期 Week 3 Python Exam 2016 Docs Faq Contributing (`大一小学期/Week_3-Python/exam/2016/docs/faq/contributing.txt`)
====================== FAQ: Contributing code
How can I get started contributing code to Django?
Thanks for asking! We've written an entire document devoted to this question.
It's titled :doc:Contributing to Django .
I submitted a bug fix in the ticket system several weeks ago. Why are you ignoring my patch?
Don't worry: We're not ignoring you!
It's important to understand there is a difference between "a ticket is being
ignored" and "a ticket has not been attended to yet." Django's ticket system
contains hundreds of open tickets, of various degrees of impact on end-user
functionality, and Django's developers have to review and prioritize.
On top of that: the people who work on Django are all volunteers. As a result,
the amount of time that we have to work on the framework is limited and will
vary from week to week depending on our spare time. If we're busy, we may not
be able to spend as much time on Django as we might want.
The best way to make sure tickets do not get hung up on the way to checkin is
to make it dead easy, even for someone who may not be intimately familiar with
that area of the code, to understand the problem and verify the fix:
Are there clear instructions on how to reproduce the bug? If this
touches a dependency (such as Pillow), a contrib module, or a specific
database, are those instructions clear enough even for someone not
familiar with it?If there are several patches attached to the ticket, is it clear what
each one does, which ones can be ignored and which matter?Does the patch include a unit test? If not, is there a very clear
explanation why not? A test expresses succinctly what the problem is,
and shows that the patch actually fixes it.
If your patch stands no chance of inclusion in Django, we won't ignore it --
we'll just close the ticket. So if your ticket is still open, it doesn't mean
we're ignoring you; it just means we haven't had time to look at it yet.
When and how might I remind the core team of a patch I care about?
A polite, well-timed message to the mailing list is one way to get attention.
To determine the right time, you need to keep an eye on the schedule. If you
post your message when the core developers are trying to hit a feature
deadline or manage a planning phase, you're not going to get the sort of
attention you require. However, if you draw attention to a ticket when the
core developers are paying particular attention to bugs -- just before a bug
fixing sprint, or in the lead up to a beta release for example -- you're much
more likely to get a productive response.
Gentle IRC reminders can also work -- again, strategically timed if possible.
During a bug sprint would be a very good time, for example.
Another way to get traction is to pull several related tickets together. When
the core developers sit down to fix a bug in an area they haven't touched for
a while, it can take a few minutes to remember all the fine details of how
that area of code works. If you collect several minor bug fixes together into
a similarly themed group, you make an attractive target, as the cost of coming
up to speed on an area of code can be spread over multiple tickets.
Please refrain from emailing core developers personally, or repeatedly raising
the same issue over and over. This sort of behavior will not gain you any
additional attention -- certainly not the attention that you need in order to
get your pet bug addressed.
But I've reminded you several times and you keep ignoring my patch!
Seriously - we're not ignoring you. If your patch stands no chance of
inclusion in Django, we'll close the ticket. For all the other tickets, we
need to prioritize our efforts, which means that some tickets will be
addressed before others.
One of the criteria that is used to prioritize bug fixes is the number of
people that will likely be affected by a given bug. Bugs that have the
potential to affect many people will generally get priority over those that
are edge cases.
Another reason that bugs might be ignored for while is if the bug is a symptom
of a larger problem. While we can spend time writing, testing and applying
lots of little patches, sometimes the right solution is to rebuild. If a
rebuild or refactor of a particular component has been proposed or is
underway, you may find that bugs affecting that component will not get as much
attention. Again, this is just a matter of prioritizing scarce resources. By
concentrating on the rebuild, we can close all the little bugs at once, and
hopefully prevent other little bugs from appearing in the future.
Whatever the reason, please keep in mind that while you may hit a particular
bug regularly, it doesn't necessarily follow that every single Django user
will hit the same bug. Different users use Django in different ways, stressing
different parts of the code under different conditions. When we evaluate the
relative priorities, we are generally trying to consider the needs of the
entire community, not just the severity for one particular user. This doesn't
mean that we think your problem is unimportant -- just that in the limited
time we have available, we will always err on the side of making 10 people
happy rather than making 1 person happy.
大一小学期 Week 3 Python Exam 2016 Docs Faq General (`大一小学期/Week_3-Python/exam/2016/docs/faq/general.txt`)
============ FAQ: General
Why does this project exist?
Django grew from a very practical need: World Online, a newspaper Web
operation, is responsible for building intensive Web applications on journalism
deadlines. In the fast-paced newsroom, World Online often has only a matter of
hours to take a complicated Web application from concept to public launch.
At the same time, the World Online Web developers have consistently been
perfectionists when it comes to following best practices of Web development.
In fall 2003, the World Online developers (Adrian Holovaty and Simon Willison)
ditched PHP and began using Python to develop its websites. As they built
intensive, richly interactive sites such as Lawrence.com, they began to extract
a generic Web development framework that let them build Web applications more
and more quickly. They tweaked this framework constantly, adding improvements
over two years.
In summer 2005, World Online decided to open-source the resulting software,
Django. Django would not be possible without a whole host of open-source
projects -- Apache, Python, and PostgreSQL_ to name a few -- and we're
thrilled to be able to give something back to the open-source community.
.. _Apache: https://httpd.apache.org/
.. _Python: https://www.python.org/
.. _PostgreSQL: http://www.postgresql.org/
What does "Django" mean, and how do you pronounce it?
Django is named after Django Reinhardt_, a jazz manouche guitarist from the 1930s
to early 1950s. To this day, he's considered one of the best guitarists of all time.
Listen to his music. You'll like it.
Django is pronounced JANG-oh. Rhymes with FANG-oh. The "D" is silent.
We've also recorded an audio clip of the pronunciation_.
.. _Django Reinhardt: https://en.wikipedia.org/wiki/Django_Reinhardt
.. _audio clip of the pronunciation: http://red-bean.com/~adrian/django_pronunciation.mp3
Is Django stable?
Yes, it's quite stable. Companies like Disqus, Instagram, Pinterest, and
Mozilla have been using Django for many years. Sites built on Django have
weathered traffic spikes of over 50 thousand hits per second.
Does Django scale?
Yes. Compared to development time, hardware is cheap, and so Django is
designed to take advantage of as much hardware as you can throw at it.
Django uses a "shared-nothing" architecture, which means you can add hardware
at any level -- database servers, caching servers or Web/application servers.
The framework cleanly separates components such as its database layer and
application layer. And it ships with a simple-yet-powerful
:doc:cache framework </topics/cache>.
Who's behind this?
Django was originally developed at World Online, the Web department of a
newspaper in Lawrence, Kansas, USA. Django's now run by an international
:doc:team of volunteers .
Which sites use Django?
DjangoSites.org_ features a constantly growing list of Django-powered sites.
.. _DjangoSites.org: https://djangosites.org
.. _faq-mtv:
Django appears to be a MVC framework, but you call the Controller the "view", and the View the "template". How come you don't use the standard names?
Well, the standard names are debatable.
In our interpretation of MVC, the "view" describes the data that gets presented
to the user. It's not necessarily how the data looks, but which data is
presented. The view describes which data you see, not how you see it. It's
a subtle distinction.
So, in our case, a "view" is the Python callback function for a particular URL,
because that callback function describes which data is presented.
Furthermore, it's sensible to separate content from presentation -- which is
where templates come in. In Django, a "view" describes which data is presented,
but a view normally delegates to a template, which describes how the data is
presented.
Where does the "controller" fit in, then? In Django's case, it's probably the
framework itself: the machinery that sends a request to the appropriate view,
according to the Django URL configuration.
If you're hungry for acronyms, you might say that Django is a "MTV" framework
-- that is, "model", "template", and "view." That breakdown makes much more
sense.
At the end of the day, of course, it comes down to getting stuff done. And,
regardless of how things are named, Django gets stuff done in a way that's most
logical to us.
does -- why doesn't Django?
We're well aware that there are other awesome Web frameworks out there, and
we're not averse to borrowing ideas where appropriate. However, Django was
developed precisely because we were unhappy with the status quo, so please be
aware that "because
to add a given feature to Django.
Why did you write all of Django from scratch, instead of using other Python libraries?
When Django was originally written a couple of years ago, Adrian and Simon
spent quite a bit of time exploring the various Python Web frameworks
available.
In our opinion, none of them were completely up to snuff.
We're picky. You might even call us perfectionists. (With deadlines.)
Over time, we stumbled across open-source libraries that did things we'd
already implemented. It was reassuring to see other people solving similar
problems in similar ways, but it was too late to integrate outside code: We'd
already written, tested and implemented our own framework bits in several
production settings -- and our own code met our needs delightfully.
In most cases, however, we found that existing frameworks/tools inevitably had
some sort of fundamental, fatal flaw that made us squeamish. No tool fit our
philosophies 100%.
Like we said: We're picky.
We've documented our philosophies on the
:doc:design philosophies page </misc/design-philosophies>.
Is Django a content-management-system (CMS)?
No, Django is not a CMS, or any sort of "turnkey product" in and of itself.
It's a Web framework; it's a programming tool that lets you build websites.
For example, it doesn't make much sense to compare Django to something like
Drupal_, because Django is something you use to create things like Drupal.
Of course, Django's automatic admin site is fantastic and timesaving -- but
the admin site is one module of Django the framework. Furthermore, although
Django has special conveniences for building "CMS-y" apps, that doesn't mean
it's not just as appropriate for building "non-CMS-y" apps (whatever that
means!).
.. _Drupal: https://drupal.org/
How can I download the Django documentation to read it offline?
The Django docs are available in the docs directory of each Django tarball
release. These docs are in reST (reStructuredText) format, and each text file
corresponds to a Web page on the official Django site.
Because the documentation is stored in revision control_, you can browse
documentation changes just like you can browse code changes.
Technically, the docs on Django's site are generated from the latest development
versions of those reST documents, so the docs on the Django site may offer more
information than the docs that come with the latest Django release.
.. _stored in revision control: https://github.com/django/django/tree/master/docs/
Where can I find Django developers for hire?
Consult our developers for hire page_ for a list of Django developers who
would be happy to help you.
You might also be interested in posting a job to https://djangogigs.com/ .
If you want to find Django-capable people in your local area, try
https://people.djangoproject.com/ .
.. _developers for hire page: https://code.djangoproject.com/wiki/DevelopersForHire
How do I cite Django?
It's difficult to give an official citation format, for two reasons: citation
formats can vary wildly between publications, and citation standards for
software are still a matter of some debate.
For example, APA style_, would dictate something like::
Django (Version 1.5) [Computer Software]. (2013). Retrieved from https://djangoproject.com.However, the only true guide is what your publisher will accept, so get a copy
of those guidelines and fill in the gaps as best you can.
If your referencing style guide requires a publisher name, use "Django Software
Foundation".
If you need a publishing location, use "Lawrence, Kansas".
If you need a web address, use https://djangoproject.com.
If you need a name, just use "Django", without any tagline.
If you need a publication date, use the year of release of the version you're
referencing (e.g., 2013 for v1.5)
.. _APA style: http://www.apastyle.org
大一小学期 Week 3 Python Exam 2016 Docs Faq Help (`大一小学期/Week_3-Python/exam/2016/docs/faq/help.txt`)
================= FAQ: Getting Help
How do I do X? Why doesn't Y work? Where can I go to get help?
If this FAQ doesn't contain an answer to your question, you might want to
try the |django-users| mailing list. Feel free to ask any question related
to installing, using, or debugging Django.
If you prefer IRC, the #django IRC channel_ on the Freenode IRC network is an
active community of helpful individuals who may be able to solve your problem.
.. _#django IRC channel: irc://irc.freenode.net/django
.. _message-does-not-appear-on-django-users:
Why hasn't my message appeared on django-users?
|django-users| has a lot of subscribers. This is good for the community, as
it means many people are available to contribute answers to questions.
Unfortunately, it also means that |django-users| is an attractive target for
spammers.
In order to combat the spam problem, when you join the |django-users| mailing
list, we manually moderate the first message you send to the list. This means
that spammers get caught, but it also means that your first question to the
list might take a little longer to get answered. We apologize for any
inconvenience that this policy may cause.
Nobody on django-users answered my question! What should I do?
Try making your question more specific, or provide a better example of your
problem.
As with most open-source mailing lists, the folks on |django-users| are
volunteers. If nobody has answered your question, it may be because nobody
knows the answer, it may be because nobody can understand the question, or it
may be that everybody that can help is busy. One thing you might try is to ask
the question on IRC -- visit the #django IRC channel_ on the Freenode IRC
network.
You might notice we have a second mailing list, called |django-developers| --
but please don't email support questions to this mailing list. This list is
for discussion of the development of Django itself. Asking a tech support
question there is considered quite impolite.
I think I've found a bug! What should I do?
Detailed instructions on how to handle a potential bug can be found in our
:ref:Guide to contributing to Django <reporting-bugs>.
I think I've found a security problem! What should I do?
If you think you've found a security problem with Django, please send a message
to [email protected]. This is a private list only open to long-time,
highly trusted Django developers, and its archives are not publicly readable.
Due to the sensitive nature of security issues, we ask that if you think you
have found a security problem, please don't send a message to one of the
public mailing lists. Django has a
:ref:policy for handling security issues <reporting-security-issues>;
while a defect is outstanding, we would like to minimize any damage that
could be inflicted through public knowledge of that defect.
.. _policy for handling security issues: ../contributing/#reporting-security-issues
大一小学期 Week 3 Python Exam 2016 Docs Faq Index (`大一小学期/Week_3-Python/exam/2016/docs/faq/index.txt`)
========== Django FAQ
.. toctree::
:maxdepth: 2
general
install
usage
help
models
admin
contributing
troubleshooting
大一小学期 Week 3 Python Exam 2016 Docs Faq Install (`大一小学期/Week_3-Python/exam/2016/docs/faq/install.txt`)
================= FAQ: Installation
How do I get started?
#. Download the code.
#. Install Django (read the :doc:installation guide ).
#. Walk through the :doc:tutorial .
#. Check out the rest of the :doc:documentation , and ask questions if you
run into trouble.
.. _Download the code: https://www.djangoproject.com/download/
.. _ask questions: https://www.djangoproject.com/community/
What are Django's prerequisites?
Django requires Python. See the table in the next question for the versions of
Python that work with each version of Django. Other Python libraries may be
required for some uses, but you'll receive an error about it as they're needed.
For a development environment -- if you just want to experiment with Django --
you don't need to have a separate Web server installed; Django comes with its
own lightweight development server. For a production environment, Django follows
the WSGI spec, :pep:3333, which means it can run on a variety of server
platforms. See :doc:Deploying Django </howto/deployment/index> for some
popular alternatives.
If you want to use Django with a database, which is probably the case, you'll
also need a database engine. PostgreSQL_ is recommended, because we're
PostgreSQL fans, and MySQL_, SQLite 3, and Oracle are also supported.
.. _Python: https://www.python.org/
.. _PostgreSQL: http://www.postgresql.org/
.. _MySQL: https://www.mysql.com/
.. _SQLite 3: https://www.sqlite.org/
.. _Oracle: http://www.oracle.com/
.. _faq-python-version-support:
What Python version can I use with Django?
============== ===============
Django version Python versions
============== ===============
1.8 2.7, 3.2 (until the end of 2016), 3.3, 3.4, 3.5
1.9, 1.10 2.7, 3.4, 3.5
1.11 2.7, 3.4, 3.5, 3.6
2.0 3.5+
============== ===============
For each version of Python, only the latest micro release (A.B.C) is officially
supported. You can find the latest micro version for each series on the Python download page <https://www.python.org/downloads/>_.
Typically, we will support a Python version up to and including the first
Django LTS release whose security support ends after security support for that
version of Python ends. For example, Python 3.3 security support ends September
2017 and Django 1.8 LTS security support ends April 2018. Therefore Django 1.8
is the last version to support Python 3.3.
What Python version should I use with Django?
As of Django 1.6, Python 3 support is considered stable and you can safely use
it in production. See also :doc:/topics/python3. However, the community is
still in the process of migrating third-party packages and applications to
Python 3.
If you're starting a new project, and the dependencies you plan to use work on
Python 3, you should use Python 3. If they don't, consider contributing to the
porting efforts, or stick to Python 2.
Since newer versions of Python are often faster, have more features, and are
better supported, all else being equal, we recommend that you use the latest
2.x.y or 3.x.y release.
You don't lose anything in Django by using an older release, but you don't take
advantage of the improvements and optimizations in newer Python releases.
Third-party applications for use with Django are, of course, free to set their
own version requirements.
Should I use the stable version or development version?
Generally, if you're using code in production, you should be using a
stable release. The Django project publishes a full stable release
every nine months or so, with bugfix updates in between. These stable
releases contain the API that is covered by our backwards
compatibility guarantees; if you write code against stable releases,
you shouldn't have any problems upgrading when the next official
version is released.
大一小学期 Week 3 Python Exam 2016 Docs Faq Models (`大一小学期/Week_3-Python/exam/2016/docs/faq/models.txt`)
========================= FAQ: Databases and models
.. _faq-see-raw-sql-queries:
How can I see the raw SQL queries Django is running?
Make sure your Django :setting:DEBUG setting is set to True.
Then, just do this::
>>> from django.db import connection
>>> connection.queries
[{'sql': 'SELECT polls_polls.id, polls_polls.question, polls_polls.pub_date FROM polls_polls',
'time': '0.002'}]connection.queries is only available if :setting:DEBUG is True.
It's a list of dictionaries in order of query execution. Each dictionary has
the following::
``sql`` -- The raw SQL statement
``time`` -- How long the statement took to execute, in seconds.connection.queries includes all SQL statements -- INSERTs, UPDATES,
SELECTs, etc. Each time your app hits the database, the query will be recorded.
If you are using :doc:multiple databases</topics/db/multi-db>, you can use the
same interface on each member of the connections dictionary::
>>> from django.db import connections
>>> connections['my_db_alias'].queriesIf you need to clear the query list manually at any point in your functions,
just call reset_queries(), like this::
from django.db import reset_queries
reset_queries()Can I use Django with a pre-existing database?
Yes. See :doc:Integrating with a legacy database </howto/legacy-databases>.
If I make changes to a model, how do I update the database?
Take a look at Django's support for :mod:schema migrations <django.db.migrations>.
If you don't mind clearing data, your project's manage.py utility has a
:djadmin:flush option to reset the database to the state it was in
immediately after :djadmin:migrate was executed.
Do Django models support multiple-column primary keys?
No. Only single-column primary keys are supported.
But this isn't an issue in practice, because there's nothing stopping you from
adding other constraints (using the unique_together model option or
creating the constraint directly in your database), and enforcing the
uniqueness at that level. Single-column primary keys are needed for things such
as the admin interface to work; e.g., you need a simple way of being able to
specify an object to edit or delete.
Does Django support NoSQL databases?
NoSQL databases are not officially supported by Django itself. There are,
however, a number of side project and forks which allow NoSQL functionality in
Django, like Django non-rel_.
You can also take a look on the wiki page_ which discusses some alternatives.
.. _Django non-rel: http://django-nonrel.org/
.. _the wiki page: https://code.djangoproject.com/wiki/NoSqlSupport
How do I add database-specific options to my CREATE TABLE statements, such as specifying MyISAM as the table type?
We try to avoid adding special cases in the Django code to accommodate all the
database-specific options such as table type, etc. If you'd like to use any of
these options, create a migration with a
:class:~django.db.migrations.operations.RunSQL operation that containsALTER TABLE statements that do what you want to do.
For example, if you're using MySQL and want your tables to use the MyISAM table
type, use the following SQL::
ALTER TABLE myapp_mytable ENGINE=MyISAM;大一小学期 Week 3 Python Exam 2016 Docs Faq Troubleshooting (`大一小学期/Week_3-Python/exam/2016/docs/faq/troubleshooting.txt`)
=============== Troubleshooting
This page contains some advice about errors and problems commonly encountered
during the development of Django applications.
.. _troubleshooting-django-admin:
Problems running django-admin
"command not found: django-admin"
:doc:django-admin </ref/django-admin> should be on your system path if you
installed Django via python setup.py. If it's not on your path, you can
find it in site-packages/django/bin, where site-packages is a directory
within your Python installation. Consider symlinking to :doc:django-admin </ref/django-admin> from some place on your path, such as
:file:/usr/local/bin.
If django-admin doesn't work but django-admin.py does, you're probably
using a version of Django that doesn't match the version of this documentation.django-admin is new in Django 1.7.
Mac OS X permissions
If you're using Mac OS X, you may see the message "permission denied" when
you try to run django-admin. This is because, on Unix-based systems like
OS X, a file must be marked as "executable" before it can be run as a program.
To do this, open Terminal.app and navigate (using the cd command) to the
directory where :doc:django-admin </ref/django-admin> is installed, then
run the command sudo chmod +x django-admin.
Miscellaneous
I'm getting a ``UnicodeDecodeError``. What am I doing wrong?
This class of errors happen when a bytestring containing non-ASCII sequences is
transformed into a Unicode string and the specified encoding is incorrect. The
output generally looks like this::
UnicodeDecodeError: 'ascii' codec can't decode byte 0x?? in position ?:
ordinal not in range(128)The resolution mostly depends on the context, however here are two common
pitfalls producing this error:
Your system locale may be a default ASCII locale, like the "C" locale on
UNIX-like systems (can be checked by thelocalecommand). If it's the
case, please refer to your system documentation to learn how you can change
this to a UTF-8 locale.You created raw bytestrings, which is easy to do on Python 2::
textmy_string = 'café'Either use the
u''prefix or even better, add thefrom __future__ import unicode_literalsline at the top of your file
so that your code will be compatible with Python 3.2 which doesn't support
theu''prefix.
Related resources:
- :doc:
Unicode in Django </ref/unicode> - https://wiki.python.org/moin/UnicodeDecodeError
大一小学期 Week 3 Python Exam 2016 Docs Faq Usage (`大一小学期/Week_3-Python/exam/2016/docs/faq/usage.txt`)
================= FAQ: Using Django
Why do I get an error about importing DJANGO_SETTINGS_MODULE?
Make sure that:
The environment variable DJANGO_SETTINGS_MODULE is set to a
fully-qualified Python module (i.e. "mysite.settings").Said module is on
sys.path(import mysite.settingsshould work).The module doesn't contain syntax errors (of course).
I can't stand your template language. Do I have to use it?
We happen to think our template engine is the best thing since chunky bacon,
but we recognize that choosing a template language runs close to religion.
There's nothing about Django that requires using the template language, so
if you're attached to Jinja2, Mako, or whatever, feel free to use those.
Do I have to use your model/database layer?
Nope. Just like the template system, the model/database layer is decoupled from
the rest of the framework.
The one exception is: If you use a different database library, you won't get to
use Django's automatically-generated admin site. That app is coupled to the
Django database layer.
How do I use image and file fields?
Using a :class:~django.db.models.FileField or an
:class:~django.db.models.ImageField in a model takes a few steps:
#. In your settings file, you'll need to define :setting:MEDIA_ROOT as
the full path to a directory where you'd like Django to store uploaded
files. (For performance, these files are not stored in the database.)
Define :setting:MEDIA_URL as the base public URL of that directory.
Make sure that this directory is writable by the Web server's user
account.
#. Add the :class:~django.db.models.FileField or
:class:~django.db.models.ImageField to your model, defining the
:attr:~django.db.models.FileField.upload_to option to specify a
subdirectory of :setting:MEDIA_ROOT to use for uploaded files.
#. All that will be stored in your database is a path to the file
(relative to :setting:MEDIA_ROOT). You'll most likely want to use the
convenience :attr:~django.db.models.fields.files.FieldFile.url attribute
provided by Django. For example, if your
:class:~django.db.models.ImageField is called mug_shot, you can get
the absolute path to your image in a template with
{{ object.mug_shot.url }}.
How do I make a variable available to all my templates?
Sometimes your templates just all need the same thing. A common example would
be dynamically-generated menus. At first glance, it seems logical to simply
add a common dictionary to the template context.
The correct solution is to use a RequestContext. Details on how to do this
are here: :ref:subclassing-context-requestcontext.
大一小学期 Week 3 Python Exam 2016 Docs Howto Auth Remote User (`大一小学期/Week_3-Python/exam/2016/docs/howto/auth-remote-user.txt`)
==================================== Authentication using ``REMOTE_USER``
This document describes how to make use of external authentication sources
(where the Web server sets the REMOTE_USER environment variable) in your
Django applications. This type of authentication solution is typically seen on
intranet sites, with single sign-on solutions such as IIS and Integrated
Windows Authentication or Apache and mod_authnz_ldap, CAS, Cosign,WebAuth, mod_auth_sspi_, etc.
.. _mod_authnz_ldap: https://httpd.apache.org/docs/2.2/mod/mod_authnz_ldap.html
.. _CAS: https://www.apereo.org/projects/cas
.. _Cosign: http://weblogin.org
.. _WebAuth: https://www.stanford.edu/services/webauth/
.. _mod_auth_sspi: http://sourceforge.net/projects/mod-auth-sspi
When the Web server takes care of authentication it typically sets theREMOTE_USER environment variable for use in the underlying application. In
Django, REMOTE_USER is made available in the :attr:request.META <django.http.HttpRequest.META> attribute. Django can be configured to make
use of the REMOTE_USER value using the RemoteUserMiddleware
or PersistentRemoteUserMiddleware, and
:class:~django.contrib.auth.backends.RemoteUserBackend classes found in
:mod:django.contrib.auth.
Configuration
First, you must add the
:class:django.contrib.auth.middleware.RemoteUserMiddleware to the
:setting:MIDDLEWARE setting after the
:class:django.contrib.auth.middleware.AuthenticationMiddleware::
MIDDLEWARE = [
'...',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.RemoteUserMiddleware',
'...',
]Next, you must replace the :class:~django.contrib.auth.backends.ModelBackend
with :class:~django.contrib.auth.backends.RemoteUserBackend in the
:setting:AUTHENTICATION_BACKENDS setting::
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.RemoteUserBackend',
]With this setup, RemoteUserMiddleware will detect the username inrequest.META['REMOTE_USER'] and will authenticate and auto-login that user
using the :class:~django.contrib.auth.backends.RemoteUserBackend.
Be aware that this particular setup disables authentication with the defaultModelBackend. This means that if the REMOTE_USER value is not set
then the user is unable to log in, even using Django's admin interface.
Adding 'django.contrib.auth.backends.ModelBackend' to theAUTHENTICATION_BACKENDS list will use ModelBackend as a fallback
if REMOTE_USER is absent, which will solve these issues.
Django's user management, such as the views in contrib.admin and
the :djadmin:createsuperuser management command, doesn't integrate with
remote users. These interfaces work with users stored in the database
regardless of AUTHENTICATION_BACKENDS.
.. note::
Since the ``RemoteUserBackend`` inherits from ``ModelBackend``, you will
still have all of the same permissions checking that is implemented in
``ModelBackend``.
Users with :attr:`is_active=False
<django.contrib.auth.models.User.is_active>` won't be allowed to
authenticate. Use
:class:`~django.contrib.auth.backends.AllowAllUsersRemoteUserBackend` if
you want to allow them to.
.. versionchanged:: 1.10
In older versions, inactive users weren't rejected as described above.If your authentication mechanism uses a custom HTTP header and notREMOTE_USER, you can subclass RemoteUserMiddleware and set theheader attribute to the desired request.META key. For example::
from django.contrib.auth.middleware import RemoteUserMiddleware
class CustomHeaderMiddleware(RemoteUserMiddleware):
header = 'HTTP_AUTHUSER'.. warning::
Be very careful if using a ``RemoteUserMiddleware`` subclass with a custom
HTTP header. You must be sure that your front-end web server always sets or
strips that header based on the appropriate authentication checks, never
permitting an end-user to submit a fake (or "spoofed") header value. Since
the HTTP headers ``X-Auth-User`` and ``X-Auth_User`` (for example) both
normalize to the ``HTTP_X_AUTH_USER`` key in ``request.META``, you must
also check that your web server doesn't allow a spoofed header using
underscores in place of dashes.
This warning doesn't apply to ``RemoteUserMiddleware`` in its default
configuration with ``header = 'REMOTE_USER'``, since a key that doesn't
start with ``HTTP_`` in ``request.META`` can only be set by your WSGI
server, not directly from an HTTP request header.If you need more control, you can create your own authentication backend
that inherits from :class:~django.contrib.auth.backends.RemoteUserBackend and
override one or more of its attributes and methods.
.. _persistent-remote-user-middleware-howto:
Using ``REMOTE_USER`` on login pages only
.. versionadded:: 1.9
The RemoteUserMiddleware authentication middleware assumes that the HTTP
request header REMOTE_USER is present with all authenticated requests. That
might be expected and practical when Basic HTTP Auth with htpasswd or other
simple mechanisms are used, but with Negotiate (GSSAPI/Kerberos) or other
resource intensive authentication methods, the authentication in the front-end
HTTP server is usually only set up for one or a few login URLs, and after
successful authentication, the application is supposed to maintain the
authenticated session itself.
:class:~django.contrib.auth.middleware.PersistentRemoteUserMiddleware
provides support for this use case. It will maintain the authenticated session
until explicit logout by the user. The class can be used as a drop-in
replacement of :class:~django.contrib.auth.middleware.RemoteUserMiddleware
in the documentation above.
大一小学期 Week 3 Python Exam 2016 Docs Howto Custom File Storage (`大一小学期/Week_3-Python/exam/2016/docs/howto/custom-file-storage.txt`)
=============================== Writing a custom storage system
.. currentmodule:: django.core.files.storage
If you need to provide custom file storage -- a common example is storing files
on some remote system -- you can do so by defining a custom storage class.
You'll need to follow these steps:
#. Your custom storage system must be a subclass of
django.core.files.storage.Storage::
from django.core.files.storage import Storage
class MyStorage(Storage):
...#. Django must be able to instantiate your storage system without any arguments.
This means that any settings should be taken from django.conf.settings::
from django.conf import settings
from django.core.files.storage import Storage
class MyStorage(Storage):
def __init__(self, option=None):
if not option:
option = settings.CUSTOM_STORAGE_OPTIONS
...#. Your storage class must implement the :meth:_open() and :meth:_save()
methods, along with any other methods appropriate to your storage class. See
below for more on these methods.
In addition, if your class provides local file storage, it must override
the path() method.
#. Your storage class must be :ref:deconstructible <custom-deconstruct-method>
so it can be serialized when it's used on a field in a migration. As long
as your field has arguments that are themselves
:ref:serializable <migration-serializing>, you can use the
django.utils.deconstruct.deconstructible class decorator for this
(that's what Django uses on FileSystemStorage).
By default, the following methods raise NotImplementedError and will
typically have to be overridden:
- :meth:
Storage.delete - :meth:
Storage.exists - :meth:
Storage.listdir - :meth:
Storage.size - :meth:
Storage.url
Note however that not all these methods are required and may be deliberately
omitted. As it happens, it is possible to leave each method unimplemented and
still have a working Storage.
By way of example, if listing the contents of certain storage backends turns
out to be expensive, you might decide not to implement Storage.listdir.
Another example would be a backend that only handles writing to files. In this
case, you would not need to implement any of the above methods.
Ultimately, which of these methods are implemented is up to you. Leaving some
methods unimplemented will result in a partial (possibly broken) interface.
You'll also usually want to use hooks specifically designed for custom storage
objects. These are:
.. method:: _open(name, mode='rb')
Required.
Called by Storage.open(), this is the actual mechanism the storage class
uses to open the file. This must return a File object, though in most cases,
you'll want to return some subclass here that implements logic specific to the
backend storage system.
.. method:: _save(name, content)
Called by Storage.save(). The name will already have gone throughget_valid_name() and get_available_name(), and the content will be aFile object itself.
Should return the actual name of name of the file saved (usually the name
passed in, but if the storage needs to change the file name return the new name
instead).
.. method:: get_valid_name(name)
Returns a filename suitable for use with the underlying storage system. Thename argument passed to this method is either the original filename sent to
the server or, if upload_to is a callable, the filename returned by that
method after any path information is removed. Override this to customize how
non-standard characters are converted to safe filenames.
.. versionchanged:: 1.9
In older versions, this method was not called when ``upload_to`` was a
callable.The code provided on Storage retains only alpha-numeric characters, periods
and underscores from the original filename, removing everything else.
.. method:: get_available_name(name, max_length=None)
Returns a filename that is available in the storage mechanism, possibly taking
the provided filename into account. The name argument passed to this method
will have already cleaned to a filename valid for the storage system, according
to the get_valid_name() method described above.
The length of the filename will not exceed max_length, if provided. If a
free unique filename cannot be found, a :exc:SuspiciousFileOperation <django.core.exceptions.SuspiciousOperation> exception is raised.
If a file with name already exists, an underscore plus a random 7 character
alphanumeric string is appended to the filename before the extension.
大一小学期 Week 3 Python Exam 2016 Docs Howto Custom Lookups (`大一小学期/Week_3-Python/exam/2016/docs/howto/custom-lookups.txt`)
============== Custom Lookups
.. currentmodule:: django.db.models
Django offers a wide variety of :ref:built-in lookups <field-lookups> for
filtering (for example, exact and icontains). This documentation
explains how to write custom lookups and how to alter the working of existing
lookups. For the API references of lookups, see the :doc:/ref/models/lookups.
A simple lookup example
Let's start with a simple custom lookup. We will write a custom lookup ne
which works opposite to exact. Author.objects.filter(name__ne='Jack')
will translate to the SQL::
"author"."name" <> 'Jack'
This SQL is backend independent, so we don't need to worry about different
databases.
There are two steps to making this work. Firstly we need to implement the
lookup, then we need to tell Django about it. The implementation is quite
straightforward::
from django.db.models import Lookup
class NotEqual(Lookup):
lookup_name = 'ne'
def as_sql(self, compiler, connection):
lhs, lhs_params = self.process_lhs(compiler, connection)
rhs, rhs_params = self.process_rhs(compiler, connection)
params = lhs_params + rhs_params
return '%s <> %s' % (lhs, rhs), paramsTo register the NotEqual lookup we will just need to callregister_lookup on the field class we want the lookup to be available. In
this case, the lookup makes sense on all Field subclasses, so we register
it with Field directly::
from django.db.models.fields import Field
Field.register_lookup(NotEqual)
Lookup registration can also be done using a decorator pattern::
from django.db.models.fields import Field
@Field.register_lookup
class NotEqualLookup(Lookup):
# ...We can now use foo__ne for any field foo. You will need to ensure that
this registration happens before you try to create any querysets using it. You
could place the implementation in a models.py file, or register the lookup
in the ready() method of an AppConfig.
Taking a closer look at the implementation, the first required attribute islookup_name. This allows the ORM to understand how to interpret name__ne
and use NotEqual to generate the SQL. By convention, these names are always
lowercase strings containing only letters, but the only hard requirement is
that it must not contain the string __.
We then need to define the as_sql method. This takes a SQLCompiler
object, called compiler, and the active database connection.SQLCompiler objects are not documented, but the only thing we need to know
about them is that they have a compile() method which returns a tuple
containing an SQL string, and the parameters to be interpolated into that
string. In most cases, you don't need to use it directly and can pass it on toprocess_lhs() and process_rhs().
A Lookup works against two values, lhs and rhs, standing for
left-hand side and right-hand side. The left-hand side is usually a field
reference, but it can be anything implementing the :ref:query expression API <query-expression>. The right-hand is the value given by the user. In the
example Author.objects.filter(name__ne='Jack'), the left-hand side is a
reference to the name field of the Author model, and 'Jack' is the
right-hand side.
We call process_lhs and process_rhs to convert them into the values we
need for SQL using the compiler object described before. These methods
return tuples containing some SQL and the parameters to be interpolated into
that SQL, just as we need to return from our as_sql method. In the above
example, process_lhs returns ('"author"."name"', []) andprocess_rhs returns ('"%s"', ['Jack']). In this example there were no
parameters for the left hand side, but this would depend on the object we have,
so we still need to include them in the parameters we return.
Finally we combine the parts into an SQL expression with <>, and supply all
the parameters for the query. We then return a tuple containing the generated
SQL string and the parameters.
A simple transformer example
The custom lookup above is great, but in some cases you may want to be able to
chain lookups together. For example, let's suppose we are building an
application where we want to make use of the abs() operator.
We have an Experiment model which records a start value, end value, and the
change (start - end). We would like to find all experiments where the change
was equal to a certain amount (Experiment.objects.filter(change__abs=27)),
or where it did not exceed a certain amount
(Experiment.objects.filter(change__abs__lt=27)).
.. note::
This example is somewhat contrived, but it nicely demonstrates the range of
functionality which is possible in a database backend independent manner,
and without duplicating functionality already in Django.
We will start by writing a AbsoluteValue transformer. This will use the SQL
function ABS() to transform the value before comparison::
from django.db.models import Transform
class AbsoluteValue(Transform):
lookup_name = 'abs'
function = 'ABS'
Next, let's register it for IntegerField::
from django.db.models import IntegerField
IntegerField.register_lookup(AbsoluteValue)
We can now run the queries we had before.Experiment.objects.filter(change__abs=27) will generate the following SQL::
SELECT ... WHERE ABS("experiments"."change") = 27By using Transform instead of Lookup it means we are able to chain
further lookups afterwards. SoExperiment.objects.filter(change__abs__lt=27) will generate the following
SQL::
SELECT ... WHERE ABS("experiments"."change") < 27Note that in case there is no other lookup specified, Django interpretschange__abs=27 as change__abs__exact=27.
When looking for which lookups are allowable after the Transform has been
applied, Django uses the output_field attribute. We didn't need to specify
this here as it didn't change, but supposing we were applying AbsoluteValue
to some field which represents a more complex type (for example a point
relative to an origin, or a complex number) then we may have wanted to specify
that the transform returns a FloatField type for further lookups. This can
be done by adding an output_field attribute to the transform::
from django.db.models import FloatField, Transform
class AbsoluteValue(Transform):
lookup_name = 'abs'
function = 'ABS'
@property
def output_field(self):
return FloatField()This ensures that further lookups like abs__lte behave as they would for
a FloatField.
Writing an efficient ``abs__lt`` lookup
When using the above written abs lookup, the SQL produced will not use
indexes efficiently in some cases. In particular, when we usechange__abs__lt=27, this is equivalent to change__gt=-27 ANDchange__lt=27. (For the lte case we could use the SQL BETWEEN).
So we would like Experiment.objects.filter(change__abs__lt=27) to generate
the following SQL::
SELECT .. WHERE "experiments"."change" < 27 AND "experiments"."change" > -27The implementation is::
from django.db.models import Lookup
class AbsoluteValueLessThan(Lookup):
lookup_name = 'lt'
def as_sql(self, compiler, connection):
lhs, lhs_params = compiler.compile(self.lhs.lhs)
rhs, rhs_params = self.process_rhs(compiler, connection)
params = lhs_params + rhs_params + lhs_params + rhs_params
return '%s < %s AND %s > -%s' % (lhs, rhs, lhs, rhs), paramsAbsoluteValue.register_lookup(AbsoluteValueLessThan)
There are a couple of notable things going on. First, AbsoluteValueLessThan
isn't calling process_lhs(). Instead it skips the transformation of thelhs done by AbsoluteValue and uses the original lhs. That is, we
want to get "experiments"."change" not ABS("experiments"."change").
Referring directly to self.lhs.lhs is safe as AbsoluteValueLessThan
can be accessed only from the AbsoluteValue lookup, that is the lhs
is always an instance of AbsoluteValue.
Notice also that as both sides are used multiple times in the query the params
need to contain lhs_params and rhs_params multiple times.
The final query does the inversion (27 to -27) directly in the
database. The reason for doing this is that if the self.rhs is something else
than a plain integer value (for example an F() reference) we can't do the
transformations in Python.
.. note::
In fact, most lookups with __abs could be implemented as range queries
like this, and on most database backends it is likely to be more sensible to
do so as you can make use of the indexes. However with PostgreSQL you may
want to add an index on abs(change) which would allow these queries to
be very efficient.
A bilateral transformer example
The AbsoluteValue example we discussed previously is a transformation which
applies to the left-hand side of the lookup. There may be some cases where you
want the transformation to be applied to both the left-hand side and the
right-hand side. For instance, if you want to filter a queryset based on the
equality of the left and right-hand side insensitively to some SQL function.
Let's examine the simple example of case-insensitive transformation here. This
transformation isn't very useful in practice as Django already comes with a bunch
of built-in case-insensitive lookups, but it will be a nice demonstration of
bilateral transformations in a database-agnostic way.
We define an UpperCase transformer which uses the SQL function UPPER() to
transform the values before comparison. We define
:attr:bilateral = True <django.db.models.Transform.bilateral> to indicate that
this transformation should apply to both lhs and rhs::
from django.db.models import Transform
class UpperCase(Transform):
lookup_name = 'upper'
function = 'UPPER'
bilateral = True
Next, let's register it::
from django.db.models import CharField, TextField
CharField.register_lookup(UpperCase)
TextField.register_lookup(UpperCase)
Now, the queryset Author.objects.filter(name__upper="doe") will generate a case
insensitive query like this::
SELECT ... WHERE UPPER("author"."name") = UPPER('doe')Writing alternative implementations for existing lookups
Sometimes different database vendors require different SQL for the same
operation. For this example we will rewrite a custom implementation for
MySQL for the NotEqual operator. Instead of <> we will be using !=
operator. (Note that in reality almost all databases support both, including
all the official databases supported by Django).
We can change the behavior on a specific backend by creating a subclass ofNotEqual with a as_mysql method::
class MySQLNotEqual(NotEqual):
def as_mysql(self, compiler, connection):
lhs, lhs_params = self.process_lhs(compiler, connection)
rhs, rhs_params = self.process_rhs(compiler, connection)
params = lhs_params + rhs_params
return '%s != %s' % (lhs, rhs), params
Field.register_lookup(MySQLNotEqual)
We can then register it with Field. It takes the place of the originalNotEqual class as it has the same lookup_name.
When compiling a query, Django first looks for as_%s % connection.vendor
methods, and then falls back to as_sql. The vendor names for the in-built
backends are sqlite, postgresql, oracle and mysql.
How Django determines the lookups and transforms which are used
In some cases you may wish to dynamically change which Transform orLookup is returned based on the name passed in, rather than fixing it. As
an example, you could have a field which stores coordinates or an arbitrary
dimension, and wish to allow a syntax like .filter(coords__x7=4) to return
the objects where the 7th coordinate has value 4. In order to do this, you
would override get_lookup with something like::
class CoordinatesField(Field):
def get_lookup(self, lookup_name):
if lookup_name.startswith('x'):
try:
dimension = int(lookup_name[1:])
except ValueError:
pass
else:
return get_coordinate_lookup(dimension)
return super(CoordinatesField, self).get_lookup(lookup_name)You would then define get_coordinate_lookup appropriately to return aLookup subclass which handles the relevant value of dimension.
There is a similarly named method called get_transform(). get_lookup()
should always return a Lookup subclass, and get_transform() aTransform subclass. It is important to remember that Transform
objects can be further filtered on, and Lookup objects cannot.
When filtering, if there is only one lookup name remaining to be resolved, we
will look for a Lookup. If there are multiple names, it will look for aTransform. In the situation where there is only one name and a Lookup
is not found, we look for a Transform and then the exact lookup on thatTransform. All call sequences always end with a Lookup. To clarify:
.filter(myfield__mylookup)will callmyfield.get_lookup('mylookup')..filter(myfield__mytransform__mylookup)will callmyfield.get_transform('mytransform'), and thenmytransform.get_lookup('mylookup')..filter(myfield__mytransform)will first callmyfield.get_lookup('mytransform'), which will fail, so it will fall back
to callingmyfield.get_transform('mytransform')and thenmytransform.get_lookup('exact').
大一小学期 Week 3 Python Exam 2016 Docs Howto Custom Management Commands (`大一小学期/Week_3-Python/exam/2016/docs/howto/custom-management-commands.txt`)
======================================== Writing custom ``django-admin`` commands
.. module:: django.core.management
Applications can register their own actions with manage.py. For example,
you might want to add a manage.py action for a Django app that you're
distributing. In this document, we will be building a custom closepoll
command for the polls application from the
:doc:tutorial.
To do this, just add a management/commands directory to the application.
Django will register a manage.py command for each Python module in that
directory whose name doesn't begin with an underscore. For example::
polls/
__init__.py
models.py
management/
__init__.py
commands/
__init__.py
_private.py
closepoll.py
tests.py
views.pyOn Python 2, be sure to include __init__.py files in both themanagement and management/commands directories as done above or your
command will not be detected.
In this example, the closepoll command will be made available to any project
that includes the polls application in :setting:INSTALLED_APPS.
The _private.py module will not be available as a management command.
The closepoll.py module has only one requirement -- it must define a classCommand that extends :class:BaseCommand or one of its
:ref:subclasses<ref-basecommand-subclasses>.
.. admonition:: Standalone scripts
Custom management commands are especially useful for running standalone
scripts or for scripts that are periodically executed from the UNIX crontab
or from Windows scheduled tasks control panel.To implement the command, edit polls/management/commands/closepoll.py to
look like this::
from django.core.management.base import BaseCommand, CommandError
from polls.models import Question as Poll
class Command(BaseCommand):
help = 'Closes the specified poll for voting'
def add_arguments(self, parser):
parser.add_argument('poll_id', nargs='+', type=int)
def handle(self, *args, **options):
for poll_id in options['poll_id']:
try:
poll = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise CommandError('Poll "%s" does not exist' % poll_id)
poll.opened = False
poll.save()
self.stdout.write(self.style.SUCCESS('Successfully closed poll "%s"' % poll_id)).. _management-commands-output:
.. note::
When you are using management commands and wish to provide console
output, you should write to self.stdout and self.stderr,
instead of printing to stdout and stderr directly. By
using these proxies, it becomes much easier to test your custom
command. Note also that you don't need to end messages with a newline
character, it will be added automatically, unless you specify the ending
parameter::
self.stdout.write("Unterminated line", ending='')The new custom command can be called using python manage.py closepoll .
The handle() method takes one or more poll_ids and sets poll.opened
to False for each one. If the user referenced any nonexistent polls, a
:exc:CommandError is raised. The poll.opened attribute does not exist in
the :doc:tutorial and was added topolls.models.Question for this example.
.. _custom-commands-options:
Accepting optional arguments
The same closepoll could be easily modified to delete a given poll instead
of closing it by accepting additional command line options. These custom
options can be added in the :meth:~BaseCommand.add_arguments method like this::
class Command(BaseCommand):
def add_arguments(self, parser):
# Positional arguments
parser.add_argument('poll_id', nargs='+', type=int)
# Named (optional) arguments
parser.add_argument(
'--delete',
action='store_true',
dest='delete',
default=False,
help='Delete poll instead of closing it',
)
def handle(self, *args, **options):
# ...
if options['delete']:
poll.delete()
# ...The option (delete in our example) is available in the options dict
parameter of the handle method. See the :py:mod:argparse Python documentation
for more about add_argument usage.
In addition to being able to add custom command line options, all
:doc:management commands</ref/django-admin> can accept some default options
such as :option:--verbosity and :option:--traceback.
.. _management-commands-and-locales:
Management commands and locales
By default, the :meth:BaseCommand.execute method deactivates translations
because some commands shipped with Django perform several tasks (for example,
user-facing content rendering and database population) that require a
project-neutral string language.
If, for some reason, your custom management command needs to use a fixed locale,
you should manually activate and deactivate it in your
:meth:~BaseCommand.handle method using the functions provided by the I18N
support code::
from django.core.management.base import BaseCommand, CommandError
from django.utils import translation
class Command(BaseCommand):
...
can_import_settings = True
def handle(self, *args, **options):
# Activate a fixed locale, e.g. Russian
translation.activate('ru')
# Or you can activate the LANGUAGE_CODE # chosen in the settings:
from django.conf import settings
translation.activate(settings.LANGUAGE_CODE)
# Your command logic here
...
translation.deactivate()Another need might be that your command simply should use the locale set in
settings and Django should be kept from deactivating it. You can achieve
it by using the :data:BaseCommand.leave_locale_alone option.
When working on the scenarios described above though, take into account that
system management commands typically have to be very careful about running in
non-uniform locales, so you might need to:
Make sure the :setting:
USE_I18Nsetting is alwaysTruewhen running
the command (this is a good example of the potential problems stemming
from a dynamic runtime environment that Django commands avoid offhand by
deactivating translations).Review the code of your command and the code it calls for behavioral
differences when locales are changed and evaluate its impact on
predictable behavior of your command.
Testing
Information on how to test custom management commands can be found in the
:ref:testing docs <topics-testing-management-commands>.
Command objects
.. class:: BaseCommand
The base class from which all management commands ultimately derive.
Use this class if you want access to all of the mechanisms which
parse the command-line arguments and work out what code to call in
response; if you don't need to change any of that behavior,
consider using one of its :ref:subclasses<ref-basecommand-subclasses>.
Subclassing the :class:BaseCommand class requires that you implement the
:meth:~BaseCommand.handle method.
Attributes
All attributes can be set in your derived class and can be used in
:class:BaseCommand’s :ref:subclasses<ref-basecommand-subclasses>.
.. attribute:: BaseCommand.can_import_settings
A boolean indicating whether the command needs to be able to
import Django settings; if ``True``, ``execute()`` will verify
that this is possible before proceeding. Default value is
``True``... attribute:: BaseCommand.help
A short description of the command, which will be printed in the
help message when the user runs the command
``python manage.py help <command>``... attribute:: BaseCommand.missing_args_message
If your command defines mandatory positional arguments, you can customize
the message error returned in the case of missing arguments. The default is
output by :py:mod:`argparse` ("too few arguments")... attribute:: BaseCommand.output_transaction
A boolean indicating whether the command outputs SQL statements; if
``True``, the output will automatically be wrapped with ``BEGIN;`` and
``COMMIT;``. Default value is ``False``... attribute:: BaseCommand.requires_migrations_checks
.. versionadded:: 1.10
A boolean; if ``True``, the command prints a warning if the set of
migrations on disk don't match the migrations in the database. A warning
doesn't prevent the command from executing. Default value is ``False``... attribute:: BaseCommand.requires_system_checks
A boolean; if ``True``, the entire Django project will be checked for
potential problems prior to executing the command. Default value is ``True``... attribute:: BaseCommand.leave_locale_alone
A boolean indicating whether the locale set in settings should be preserved
during the execution of the command instead of being forcibly set to 'en-us'.
Default value is ``False``.
Make sure you know what you are doing if you decide to change the value of
this option in your custom command if it creates database content that
is locale-sensitive and such content shouldn't contain any translations
(like it happens e.g. with django.contrib.auth permissions) as making the
locale differ from the de facto default 'en-us' might cause unintended
effects. Seethe `Management commands and locales`_ section above for
further details.
This option can't be ``False`` when the
:data:`~BaseCommand.can_import_settings` option is set to ``False`` too
because attempting to set the locale needs access to settings. This
condition will generate a :exc:`CommandError`... attribute:: BaseCommand.style
An instance attribute that helps create colored output when writing to
``stdout`` or ``stderr``. For example::
self.stdout.write(self.style.SUCCESS('...'))
See :ref:`syntax-coloring` to learn how to modify the color palette and to
see the available styles (use uppercased versions of the "roles" described
in that section).
If you pass the :option:`--no-color` option when running your command, all
``self.style()`` calls will return the original string uncolored.Methods
:class:BaseCommand has a few methods that can be overridden but only
the :meth:~BaseCommand.handle method must be implemented.
.. admonition:: Implementing a constructor in a subclass
If you implement ``__init__`` in your subclass of :class:`BaseCommand`,
you must call :class:`BaseCommand`’s ``__init__``::
class Command(BaseCommand):
def __init__(self, *args, **kwargs):
super(Command, self).__init__(*args, **kwargs)
# ..... method:: BaseCommand.add_arguments(parser)
Entry point to add parser arguments to handle command line arguments passed
to the command. Custom commands should override this method to add both
positional and optional arguments accepted by the command. Calling
``super()`` is not needed when directly subclassing ``BaseCommand``... method:: BaseCommand.get_version()
Returns the Django version, which should be correct for all built-in Django
commands. User-supplied commands can override this method to return their
own version... method:: BaseCommand.execute(*args, **options)
Tries to execute this command, performing system checks if needed (as
controlled by the :attr:`requires_system_checks` attribute). If the command
raises a :exc:`CommandError`, it's intercepted and printed to stderr... admonition:: Calling a management command in your code
``execute()`` should not be called directly from your code to execute a
command. Use :func:`~django.core.management.call_command` instead... method:: BaseCommand.handle(*args, **options)
The actual logic of the command. Subclasses must implement this method.
It may return a Unicode string which will be printed to ``stdout`` (wrapped
by ``BEGIN;`` and ``COMMIT;`` if :attr:`output_transaction` is ``True``)... method:: BaseCommand.check(app_configs=None, tags=None, display_num_errors=False)
Uses the system check framework to inspect the entire Django project for
potential problems. Serious problems are raised as a :exc:`CommandError`;
warnings are output to stderr; minor notifications are output to stdout.
If ``app_configs`` and ``tags`` are both ``None``, all system checks are
performed. ``tags`` can be a list of check tags, like ``compatibility`` or
``models``... _ref-basecommand-subclasses:
``BaseCommand`` subclasses
.. class:: AppCommand
A management command which takes one or more installed application labels as
arguments, and does something with each of them.
Rather than implementing :meth:~BaseCommand.handle, subclasses must
implement :meth:~AppCommand.handle_app_config, which will be called once for
each application.
.. method:: AppCommand.handle_app_config(app_config, **options)
Perform the command's actions for ``app_config``, which will be an
:class:`~django.apps.AppConfig` instance corresponding to an application
label given on the command line... class:: LabelCommand
A management command which takes one or more arbitrary arguments (labels) on
the command line, and does something with each of them.
Rather than implementing :meth:~BaseCommand.handle, subclasses must implement
:meth:~LabelCommand.handle_label, which will be called once for each label.
.. method:: LabelCommand.handle_label(label, **options)
Perform the command's actions for ``label``, which will be the string as
given on the command line.Command exceptions
.. exception:: CommandError
Exception class indicating a problem while executing a management command.
If this exception is raised during the execution of a management command from a
command line console, it will be caught and turned into a nicely-printed error
message to the appropriate output stream (i.e., stderr); as a result, raising
this exception (with a sensible description of the error) is the preferred way
to indicate that something has gone wrong in the execution of a command.
If a management command is called from code through
:func:~django.core.management.call_command, it's up to you to catch the
exception when needed.
大一小学期 Week 3 Python Exam 2016 Docs Howto Custom Model Fields (`大一小学期/Week_3-Python/exam/2016/docs/howto/custom-model-fields.txt`)
=========================== Writing custom model fields
.. currentmodule:: django.db.models
Introduction
The :doc:model reference </topics/db/models> documentation explains how to use
Django's standard field classes -- :class:~django.db.models.CharField,
:class:~django.db.models.DateField, etc. For many purposes, those classes are
all you'll need. Sometimes, though, the Django version won't meet your precise
requirements, or you'll want to use a field that is entirely different from
those shipped with Django.
Django's built-in field types don't cover every possible database column type --
only the common types, such as VARCHAR and INTEGER. For more obscure
column types, such as geographic polygons or even user-created types such asPostgreSQL custom types_, you can define your own Django Field subclasses.
.. _PostgreSQL custom types: http://www.postgresql.org/docs/current/interactive/sql-createtype.html
Alternatively, you may have a complex Python object that can somehow be
serialized to fit into a standard database column type. This is another case
where a Field subclass will help you use your object with your models.
Our example object
Creating custom fields requires a bit of attention to detail. To make things
easier to follow, we'll use a consistent example throughout this document:
wrapping a Python object representing the deal of cards in a hand of Bridge_.
Don't worry, you don't have to know how to play Bridge to follow this example.
You only need to know that 52 cards are dealt out equally to four players, who
are traditionally called north, east, south and west. Our class looks
something like this::
class Hand(object):
"""A hand of cards (bridge style)"""
def __init__(self, north, east, south, west):
# Input parameters are lists of cards ('Ah', '9s', etc.)
self.north = north
self.east = east
self.south = south
self.west = west
# ... (other possibly useful methods omitted) ..... _Bridge: https://en.wikipedia.org/wiki/Contract_bridge
This is just an ordinary Python class, with nothing Django-specific about it.
We'd like to be able to do things like this in our models (we assume thehand attribute on the model is an instance of Hand)::
example = MyModel.objects.get(pk=1)
print(example.hand.north)
new_hand = Hand(north, east, south, west)
example.hand = new_hand
example.save()We assign to and retrieve from the hand attribute in our model just like
any other Python class. The trick is to tell Django how to handle saving and
loading such an object.
In order to use the Hand class in our models, we do not have to change
this class at all. This is ideal, because it means you can easily write
model support for existing classes where you cannot change the source code.
.. note::
You might only be wanting to take advantage of custom database column
types and deal with the data as standard Python types in your models;
strings, or floats, for example. This case is similar to our Hand
example and we'll note any differences as we go along.
Background theory
Database storage
The simplest way to think of a model field is that it provides a way to take a
normal Python object -- string, boolean, datetime, or something more
complex like Hand -- and convert it to and from a format that is useful
when dealing with the database (and serialization, but, as we'll see later,
that falls out fairly naturally once you have the database side under control).
Fields in a model must somehow be converted to fit into an existing database
column type. Different databases provide different sets of valid column types,
but the rule is still the same: those are the only types you have to work
with. Anything you want to store in the database must fit into one of
those types.
Normally, you're either writing a Django field to match a particular database
column type, or there's a fairly straightforward way to convert your data to,
say, a string.
For our Hand example, we could convert the card data to a string of 104
characters by concatenating all the cards together in a pre-determined order --
say, all the north cards first, then the east, south and west cards. SoHand objects can be saved to text or character columns in the database.
What does a field class do?
All of Django's fields (and when we say fields in this document, we always
mean model fields and not :doc:form fields </ref/forms/fields>) are subclasses
of :class:django.db.models.Field. Most of the information that Django records
about a field is common to all fields -- name, help text, uniqueness and so
forth. Storing all that information is handled by Field. We'll get into the
precise details of what Field can do later on; for now, suffice it to say
that everything descends from Field and then customizes key pieces of the
class behavior.
It's important to realize that a Django field class is not what is stored in
your model attributes. The model attributes contain normal Python objects. The
field classes you define in a model are actually stored in the Meta class
when the model class is created (the precise details of how this is done are
unimportant here). This is because the field classes aren't necessary when
you're just creating and modifying attributes. Instead, they provide the
machinery for converting between the attribute value and what is stored in the
database or sent to the :doc:serializer </topics/serialization>.
Keep this in mind when creating your own custom fields. The Django Field
subclass you write provides the machinery for converting between your Python
instances and the database/serializer values in various ways (there are
differences between storing a value and using a value for lookups, for
example). If this sounds a bit tricky, don't worry -- it will become clearer in
the examples below. Just remember that you will often end up creating two
classes when you want a custom field:
The first class is the Python object that your users will manipulate.
They will assign it to the model attribute, they will read from it for
displaying purposes, things like that. This is theHandclass in our
example.The second class is the
Fieldsubclass. This is the class that knows
how to convert your first class back and forth between its permanent
storage form and the Python form.
Writing a field subclass
When planning your :class:~django.db.models.Field subclass, first give some
thought to which existing :class:~django.db.models.Field class your new field
is most similar to. Can you subclass an existing Django field and save yourself
some work? If not, you should subclass the :class:~django.db.models.Field
class, from which everything is descended.
Initializing your new field is a matter of separating out any arguments that are
specific to your case from the common arguments and passing the latter to the__init__() method of :class:~django.db.models.Field (or your parent
class).
In our example, we'll call our field HandField. (It's a good idea to call
your :class:~django.db.models.Field subclass <Something>Field, so it's
easily identifiable as a :class:~django.db.models.Field subclass.) It doesn't
behave like any existing field, so we'll subclass directly from
:class:~django.db.models.Field::
from django.db import models
class HandField(models.Field):
description = "A hand of cards (bridge style)"
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 104
super(HandField, self).__init__(*args, **kwargs)Our HandField accepts most of the standard field options (see the list
below), but we ensure it has a fixed length, since it only needs to hold 52
card values plus their suits; 104 characters in total.
.. note::
Many of Django's model fields accept options that they don't do anything
with. For example, you can pass both
:attr:`~django.db.models.Field.editable` and
:attr:`~django.db.models.DateField.auto_now` to a
:class:`django.db.models.DateField` and it will simply ignore the
:attr:`~django.db.models.Field.editable` parameter
(:attr:`~django.db.models.DateField.auto_now` being set implies
``editable=False``). No error is raised in this case.
This behavior simplifies the field classes, because they don't need to
check for options that aren't necessary. They just pass all the options to
the parent class and then don't use them later on. It's up to you whether
you want your fields to be more strict about the options they select, or to
use the simpler, more permissive behavior of the current fields.The Field.__init__() method takes the following parameters:
- :attr:
~django.db.models.Field.verbose_name name- :attr:
~django.db.models.Field.primary_key - :attr:
~django.db.models.CharField.max_length - :attr:
~django.db.models.Field.unique - :attr:
~django.db.models.Field.blank - :attr:
~django.db.models.Field.null - :attr:
~django.db.models.Field.db_index rel: Used for related fields (like :class:ForeignKey). For advanced
use only.- :attr:
~django.db.models.Field.default - :attr:
~django.db.models.Field.editable serialize: IfFalse, the field will not be serialized when the model
is passed to Django's :doc:serializers </topics/serialization>. Defaults toTrue.- :attr:
~django.db.models.Field.unique_for_date - :attr:
~django.db.models.Field.unique_for_month - :attr:
~django.db.models.Field.unique_for_year - :attr:
~django.db.models.Field.choices - :attr:
~django.db.models.Field.help_text - :attr:
~django.db.models.Field.db_column - :attr:
~django.db.models.Field.db_tablespace: Only for index creation, if the
backend supports :doc:tablespaces </topics/db/tablespaces>. You can usually
ignore this option. - :attr:
~django.db.models.Field.auto_created:Trueif the field was
automatically created, as for the :class:~django.db.models.OneToOneField
used by model inheritance. For advanced use only.
All of the options without an explanation in the above list have the same
meaning they do for normal Django fields. See the :doc:field documentation </ref/models/fields> for examples and details.
.. _custom-field-deconstruct-method:
Field deconstruction
The counterpoint to writing your __init__() method is writing thedeconstruct() method. This method tells Django how to take an instance
of your new field and reduce it to a serialized form - in particular, what
arguments to pass to __init__() to re-create it.
If you haven't added any extra options on top of the field you inherited from,
then there's no need to write a new deconstruct() method. If, however,
you're changing the arguments passed in __init__() (like we are inHandField), you'll need to supplement the values being passed.
The contract of deconstruct() is simple; it returns a tuple of four items:
the field's attribute name, the full import path of the field class, the
positional arguments (as a list), and the keyword arguments (as a dict). Note
this is different from the deconstruct() method :ref:for custom classes <custom-deconstruct-method> which returns a tuple of three things.
As a custom field author, you don't need to care about the first two values;
the base Field class has all the code to work out the field's attribute
name and import path. You do, however, have to care about the positional
and keyword arguments, as these are likely the things you are changing.
For example, in our HandField class we're always forcibly setting
max_length in __init__(). The deconstruct() method on the base Field
class will see this and try to return it in the keyword arguments; thus,
we can drop it from the keyword arguments for readability::
from django.db import models
class HandField(models.Field):
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 104
super(HandField, self).__init__(*args, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super(HandField, self).deconstruct()
del kwargs["max_length"]
return name, path, args, kwargsIf you add a new keyword argument, you need to write code to put its value
into kwargs yourself::
from django.db import models
class CommaSepField(models.Field):
"Implements comma-separated storage of lists"
def __init__(self, separator=",", *args, **kwargs):
self.separator = separator
super(CommaSepField, self).__init__(*args, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super(CommaSepField, self).deconstruct()
# Only include kwarg if it's not the default
if self.separator != ",":
kwargs['separator'] = self.separator
return name, path, args, kwargsMore complex examples are beyond the scope of this document, but remember -
for any configuration of your Field instance, deconstruct() must return
arguments that you can pass to __init__ to reconstruct that state.
Pay extra attention if you set new default values for arguments in theField superclass; you want to make sure they're always included, rather
than disappearing if they take on the old default value.
In addition, try to avoid returning values as positional arguments; where
possible, return values as keyword arguments for maximum future compatibility.
Of course, if you change the names of things more often than their position
in the constructor's argument list, you might prefer positional, but bear in
mind that people will be reconstructing your field from the serialized version
for quite a while (possibly years), depending how long your migrations live for.
You can see the results of deconstruction by looking in migrations that include
the field, and you can test deconstruction in unit tests by just deconstructing
and reconstructing the field::
name, path, args, kwargs = my_field_instance.deconstruct()
new_instance = MyField(*args, **kwargs)
self.assertEqual(my_field_instance.some_attribute, new_instance.some_attribute)Changing a custom field's base class
You can't change the base class of a custom field because Django won't detect
the change and make a migration for it. For example, if you start with::
class CustomCharField(models.CharField):
...and then decide that you want to use TextField instead, you can't change
the subclass like this::
class CustomCharField(models.TextField):
...Instead, you must create a new custom field class and update your models to
reference it::
class CustomCharField(models.CharField):
...
class CustomTextField(models.TextField):
...As discussed in :ref:removing fields <migrations-removing-model-fields>, you
must retain the original CustomCharField class as long as you have
migrations that reference it.
Documenting your custom field
As always, you should document your field type, so users will know what it is.
In addition to providing a docstring for it, which is useful for developers,
you can also allow users of the admin app to see a short description of the
field type via the :doc:django.contrib.admindocs </ref/contrib/admin/admindocs> application. To do this simply provide
descriptive text in a :attr:~Field.description class attribute of your custom
field. In the above example, the description displayed by the admindocs
application for a HandField will be 'A hand of cards (bridge style)'.
In the :mod:django.contrib.admindocs display, the field description is
interpolated with field.__dict__ which allows the description to
incorporate arguments of the field. For example, the description for
:class:~django.db.models.CharField is::
description = _("String (up to %(max_length)s)")Useful methods
Once you've created your :class:~django.db.models.Field subclass, you might
consider overriding a few standard methods, depending on your field's behavior.
The list of methods below is in approximately decreasing order of importance,
so start from the top.
.. _custom-database-types:
Custom database types
Say you've created a PostgreSQL custom type called ``mytype``. You can
subclass ``Field`` and implement the :meth:`~Field.db_type` method, like so::
from django.db import models
class MytypeField(models.Field):
def db_type(self, connection):
return 'mytype'
Once you have ``MytypeField``, you can use it in any model, just like any other
``Field`` type::
class Person(models.Model):
name = models.CharField(max_length=80)
something_else = MytypeField()
If you aim to build a database-agnostic application, you should account for
differences in database column types. For example, the date/time column type
in PostgreSQL is called ``timestamp``, while the same column in MySQL is called
``datetime``. The simplest way to handle this in a :meth:`~Field.db_type`
method is to check the ``connection.settings_dict['ENGINE']`` attribute.
For example::
class MyDateField(models.Field):
def db_type(self, connection):
if connection.settings_dict['ENGINE'] == 'django.db.backends.mysql':
return 'datetime'
else:
return 'timestamp'
The :meth:`~Field.db_type` and :meth:`~Field.rel_db_type` methods are called by
Django when the framework constructs the ``CREATE TABLE`` statements for your
application -- that is, when you first create your tables. The methods are also
called when constructing a ``WHERE`` clause that includes the model field --
that is, when you retrieve data using QuerySet methods like ``get()``,
``filter()``, and ``exclude()`` and have the model field as an argument. They
are not called at any other time, so it can afford to execute slightly complex
code, such as the ``connection.settings_dict`` check in the above example.
Some database column types accept parameters, such as ``CHAR(25)``, where the
parameter ``25`` represents the maximum column length. In cases like these,
it's more flexible if the parameter is specified in the model rather than being
hard-coded in the ``db_type()`` method. For example, it wouldn't make much
sense to have a ``CharMaxlength25Field``, shown here::
# This is a silly example of hard-coded parameters.
class CharMaxlength25Field(models.Field):
def db_type(self, connection):
return 'char(25)'
# In the model:
class MyModel(models.Model):
# ...
my_field = CharMaxlength25Field()
The better way of doing this would be to make the parameter specifiable at run
time -- i.e., when the class is instantiated. To do that, just implement
``Field.__init__()``, like so::
# This is a much more flexible example.
class BetterCharField(models.Field):
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length
super(BetterCharField, self).__init__(*args, **kwargs)
def db_type(self, connection):
return 'char(%s)' % self.max_length
# In the model:
class MyModel(models.Model):
# ...
my_field = BetterCharField(25)
Finally, if your column requires truly complex SQL setup, return ``None`` from
:meth:`.db_type`. This will cause Django's SQL creation code to skip
over this field. You are then responsible for creating the column in the right
table in some other way, of course, but this gives you a way to tell Django to
get out of the way.
The :meth:`~Field.rel_db_type` method is called by fields such as ``ForeignKey``
and ``OneToOneField`` that point to another field to determine their database
column data types. For example, if you have an ``UnsignedAutoField``, you also
need the foreign keys that point to that field to use the same data type::
# MySQL unsigned integer (range 0 to 4294967295).
class UnsignedAutoField(models.AutoField):
def db_type(self, connection):
return 'integer UNSIGNED AUTO_INCREMENT'
def rel_db_type(self, connection):
return 'integer UNSIGNED'
.. versionadded:: 1.10
The :meth:`~Field.rel_db_type` method was added.
.. _converting-values-to-python-objects:
Converting values to Python objectsIf your custom :class:~Field class deals with data structures that are more
complex than strings, dates, integers, or floats, then you may need to override
:meth:~Field.from_db_value and :meth:~Field.to_python.
If present for the field subclass, from_db_value() will be called in all
circumstances when the data is loaded from the database, including in
aggregates and :meth:~django.db.models.query.QuerySet.values calls.
to_python() is called by deserialization and during the
:meth:~django.db.models.Model.clean method used from forms.
As a general rule, to_python() should deal gracefully with any of the
following arguments:
An instance of the correct type (e.g.,
Handin our ongoing example).A string
None(if the field allowsnull=True)
In our HandField class, we're storing the data as a VARCHAR field in the
database, so we need to be able to process strings and None in thefrom_db_value(). In to_python(), we need to also handle Hand
instances::
import re
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import ugettext_lazy as _
def parse_hand(hand_string):
"""Takes a string of cards and splits into a full hand."""
p1 = re.compile('.{26}')
p2 = re.compile('..')
args = [p2.findall(x) for x in p1.findall(hand_string)]
if len(args) != 4:
raise ValidationError(_("Invalid input for a Hand instance"))
return Hand(*args)
class HandField(models.Field):
# ...
def from_db_value(self, value, expression, connection, context):
if value is None:
return value
return parse_hand(value)
def to_python(self, value):
if isinstance(value, Hand):
return value
if value is None:
return value
return parse_hand(value)Notice that we always return a Hand instance from these methods. That's the
Python object type we want to store in the model's attribute.
For to_python(), if anything goes wrong during value conversion, you should
raise a :exc:~django.core.exceptions.ValidationError exception.
.. _converting-python-objects-to-query-values:
Converting Python objects to query values
Since using a database requires conversion in both ways, if you override
:meth:`~Field.to_python` you also have to override :meth:`~Field.get_prep_value`
to convert Python objects back to query values.
For example::
class HandField(models.Field):
# ...
def get_prep_value(self, value):
return ''.join([''.join(l) for l in (value.north,
value.east, value.south, value.west)])
.. warning::
If your custom field uses the ``CHAR``, ``VARCHAR`` or ``TEXT``
types for MySQL, you must make sure that :meth:`.get_prep_value`
always returns a string type. MySQL performs flexible and unexpected
matching when a query is performed on these types and the provided
value is an integer, which can cause queries to include unexpected
objects in their results. This problem cannot occur if you always
return a string type from :meth:`.get_prep_value`.
.. _converting-query-values-to-database-values:
Converting query values to database valuesSome data types (for example, dates) need to be in a specific format
before they can be used by a database backend.
:meth:~Field.get_db_prep_value is the method where those conversions should
be made. The specific connection that will be used for the query is
passed as the connection parameter. This allows you to use
backend-specific conversion logic if it is required.
For example, Django uses the following method for its
:class:BinaryField::
def get_db_prep_value(self, value, connection, prepared=False):
value = super(BinaryField, self).get_db_prep_value(value, connection, prepared)
if value is not None:
return connection.Database.Binary(value)
return valueIn case your custom field needs a special conversion when being saved that is
not the same as the conversion used for normal query parameters, you can
override :meth:~Field.get_db_prep_save.
.. _preprocessing-values-before-saving:
Preprocessing values before saving
If you want to preprocess the value just before saving, you can use
:meth:`~Field.pre_save`. For example, Django's
:class:`~django.db.models.DateTimeField` uses this method to set the attribute
correctly in the case of :attr:`~django.db.models.DateField.auto_now` or
:attr:`~django.db.models.DateField.auto_now_add`.
If you do override this method, you must return the value of the attribute at
the end. You should also update the model's attribute if you make any changes
to the value so that code holding references to the model will always see the
correct value.
.. _specifying-form-field-for-model-field:
Specifying the form field for a model fieldTo customize the form field used by :class:~django.forms.ModelForm, you can
override :meth:~Field.formfield.
The form field class can be specified via the form_class andchoices_form_class arguments; the latter is used if the field has choices
specified, the former otherwise. If these arguments are not provided,
:class:~django.forms.CharField or :class:~django.forms.TypedChoiceField
will be used.
All of the kwargs dictionary is passed directly to the form field's__init__() method. Normally, all you need to do is set up a good default
for the form_class (and maybe choices_form_class) argument and then
delegate further handling to the parent class. This might require you to write
a custom form field (and even a form widget). See the :doc:forms documentation </topics/forms/index> for information about this.
Continuing our ongoing example, we can write the :meth:~Field.formfield method
as::
class HandField(models.Field):
# ...
def formfield(self, **kwargs):
# This is a fairly standard way to set up some defaults
# while letting the caller override them.
defaults = {'form_class': MyFormField}
defaults.update(kwargs)
return super(HandField, self).formfield(**defaults)This assumes we've imported a MyFormField field class (which has its own
default widget). This document doesn't cover the details of writing custom form
fields.
.. _helper functions: ../forms/#generating-forms-for-models
.. _forms documentation: ../forms/
.. _emulating-built-in-field-types:
Emulating built-in field types
If you have created a :meth:`.db_type` method, you don't need to worry about
:meth:`.get_internal_type` -- it won't be used much. Sometimes, though, your
database storage is similar in type to some other field, so you can use that
other field's logic to create the right column.
For example::
class HandField(models.Field):
# ...
def get_internal_type(self):
return 'CharField'
No matter which database backend we are using, this will mean that
:djadmin:`migrate` and other SQL commands create the right column type for
storing a string.
If :meth:`.get_internal_type` returns a string that is not known to Django for
the database backend you are using -- that is, it doesn't appear in
``django.db.backends.<db_name>.base.DatabaseWrapper.data_types`` -- the string
will still be used by the serializer, but the default :meth:`~Field.db_type`
method will return ``None``. See the documentation of :meth:`~Field.db_type`
for reasons why this might be useful. Putting a descriptive string in as the
type of the field for the serializer is a useful idea if you're ever going to
be using the serializer output in some other place, outside of Django.
.. _converting-model-field-to-serialization:
Converting field data for serializationTo customize how the values are serialized by a serializer, you can override
:meth:~Field.value_to_string. Using value_from_object() is the best way
to get the field's value prior to serialization. For example, since ourHandField uses strings for its data storage anyway, we can reuse some
existing conversion code::
class HandField(models.Field):
# ...
def value_to_string(self, obj):
value = self.value_from_object(obj)
return self.get_prep_value(value)Some general advice
Writing a custom field can be a tricky process, particularly if you're doing
complex conversions between your Python types and your database and
serialization formats. Here are a couple of tips to make things go more
smoothly:
Look at the existing Django fields (in
:file:django/db/models/fields/__init__.py) for inspiration. Try to find
a field that's similar to what you want and extend it a little bit,
instead of creating an entirely new field from scratch.Put a
__str__()(__unicode__()on Python 2) method on the class you're
wrapping up as a field. There are a lot of places where the default
behavior of the field code is to call
:func:~django.utils.encoding.force_texton the value. (In our
examples in this document,valuewould be aHandinstance, not aHandField). So if your__str__()method (__unicode__()on
Python 2) automatically converts to the string form of your Python object,
you can save yourself a lot of work.
Writing a ``FileField`` subclass
In addition to the above methods, fields that deal with files have a few other
special requirements which must be taken into account. The majority of the
mechanics provided by FileField, such as controlling database storage and
retrieval, can remain unchanged, leaving subclasses to deal with the challenge
of supporting a particular type of file.
Django provides a File class, which is used as a proxy to the file's
contents and operations. This can be subclassed to customize how the file is
accessed, and what methods are available. It lives atdjango.db.models.fields.files, and its default behavior is explained in the
:doc:file documentation </ref/files/file>.
Once a subclass of File is created, the new FileField subclass must be
told to use it. To do so, simply assign the new File subclass to the specialattr_class attribute of the FileField subclass.
A few suggestions
In addition to the above details, there are a few guidelines which can greatly
improve the efficiency and readability of the field's code.
The source for Django's own
ImageField(indjango/db/models/fields/files.py) is a great example of how to
subclassFileFieldto support a particular type of file, as it
incorporates all of the techniques described above.Cache file attributes wherever possible. Since files may be stored in
remote storage systems, retrieving them may cost extra time, or even
money, that isn't always necessary. Once a file is retrieved to obtain
some data about its content, cache as much of that data as possible to
reduce the number of times the file must be retrieved on subsequent
calls for that information.
大一小学期 Week 3 Python Exam 2016 Docs Howto Custom Template Tags (`大一小学期/Week_3-Python/exam/2016/docs/howto/custom-template-tags.txt`)
================================ Custom template tags and filters
Django's template language comes with a wide variety of :doc:built-in tags and filters </ref/templates/builtins> designed to address the
presentation logic needs of your application. Nevertheless, you may
find yourself needing functionality that is not covered by the core
set of template primitives. You can extend the template engine by
defining custom tags and filters using Python, and then make them
available to your templates using the :ttag:{% load %}<load> tag.
Code layout
The most common place to specify custom template tags and filters is inside
a Django app. If they relate to an existing app, it makes sense to bundle them
there; otherwise, they can be added to a new app. When a Django app is added
to :setting:INSTALLED_APPS, any tags it defines in the conventional location
described below are automatically made available to load within templates.
The app should contain a templatetags directory, at the same level asmodels.py, views.py, etc. If this doesn't already exist, create it -
don't forget the __init__.py file to ensure the directory is treated as a
Python package.
.. admonition:: Development server won't automatically restart
After adding the ``templatetags`` module, you will need to restart your
server before you can use the tags or filters in templates.Your custom tags and filters will live in a module inside the templatetags
directory. The name of the module file is the name you'll use to load the tags
later, so be careful to pick a name that won't clash with custom tags and
filters in another app.
For example, if your custom tags/filters are in a file calledpoll_extras.py, your app layout might look like this::
polls/
__init__.py
models.py
templatetags/
__init__.py
poll_extras.py
views.pyAnd in your template you would use the following:
.. code-block:: html+django
{% load poll_extras %}The app that contains the custom tags must be in :setting:INSTALLED_APPS in
order for the :ttag:{% load %}<load> tag to work. This is a security feature:
It allows you to host Python code for many template libraries on a single host
machine without enabling access to all of them for every Django installation.
There's no limit on how many modules you put in the templatetags package.
Just keep in mind that a :ttag:{% load %}<load> statement will load
tags/filters for the given Python module name, not the name of the app.
To be a valid tag library, the module must contain a module-level variable
named register that is a template.Library instance, in which all the
tags and filters are registered. So, near the top of your module, put the
following::
from django import template
register = template.Library().. versionadded:: 1.9
Alternatively, template tag modules can be registered through the'libraries' argument to
:class:~django.template.backends.django.DjangoTemplates. This is useful if
you want to use a different label from the template tag module name when
loading template tags. It also enables you to register tags without installing
an application.
.. admonition:: Behind the scenes
For a ton of examples, read the source code for Django's default filters
and tags. They're in ``django/template/defaultfilters.py`` and
``django/template/defaulttags.py``, respectively.
For more information on the :ttag:`load` tag, read its documentation... _howto-writing-custom-template-filters:
Writing custom template filters
Custom filters are just Python functions that take one or two arguments:
- The value of the variable (input) -- not necessarily a string.
- The value of the argument -- this can have a default value, or be left
out altogether.
For example, in the filter {{ var|foo:"bar" }}, the filter foo would be
passed the variable var and the argument "bar".
Since the template language doesn't provide exception handling, any exception
raised from a template filter will be exposed as a server error. Thus, filter
functions should avoid raising exceptions if there is a reasonable fallback
value to return. In case of input that represents a clear bug in a template,
raising an exception may still be better than silent failure which hides the
bug.
Here's an example filter definition::
def cut(value, arg):
"""Removes all values of arg from the given string"""
return value.replace(arg, '')And here's an example of how that filter would be used:
.. code-block:: html+django
{{ somevariable|cut:"0" }}Most filters don't take arguments. In this case, just leave the argument out of
your function. Example::
def lower(value): # Only one argument.
"""Converts a string into all lowercase"""
return value.lower()Registering custom filters
.. method:: django.template.Library.filter()
Once you've written your filter definition, you need to register it with
your Library instance, to make it available to Django's template language::
register.filter('cut', cut)
register.filter('lower', lower)The Library.filter() method takes two arguments:
- The name of the filter -- a string.
- The compilation function -- a Python function (not the name of the
function as a string).
You can use register.filter() as a decorator instead::
@register.filter(name='cut')
def cut(value, arg):
return value.replace(arg, '')
@register.filter
def lower(value):
return value.lower()If you leave off the name argument, as in the second example above, Django
will use the function's name as the filter name.
Finally, register.filter() also accepts three keyword arguments,is_safe, needs_autoescape, and expects_localtime. These arguments
are described in :ref:filters and auto-escaping <filters-auto-escaping> and
:ref:filters and time zones <filters-timezones> below.
Template filters that expect strings
.. method:: django.template.defaultfilters.stringfilter()
If you're writing a template filter that only expects a string as the first
argument, you should use the decorator stringfilter. This will
convert an object to its string value before being passed to your function::
from django import template
from django.template.defaultfilters import stringfilter
register = template.Library()
@register.filter
@stringfilter
def lower(value):
return value.lower()This way, you'll be able to pass, say, an integer to this filter, and it
won't cause an AttributeError (because integers don't have lower()
methods).
.. _filters-auto-escaping:
Filters and auto-escaping
When writing a custom filter, give some thought to how the filter will interact
with Django's auto-escaping behavior. Note that three types of strings can be
passed around inside the template code:
Raw strings are the native Python
strorunicodetypes. On
output, they're escaped if auto-escaping is in effect and presented
unchanged, otherwise.Safe strings are strings that have been marked safe from further
escaping at output time. Any necessary escaping has already been done.
They're commonly used for output that contains raw HTML that is intended
to be interpreted as-is on the client side.Internally, these strings are of type
SafeBytesorSafeText.
They share a common base class ofSafeData, so you can test
for them using code like::textif isinstance(value, SafeData): # Do something with the "safe" string. ...
Template filter code falls into one of two situations:
Your filter does not introduce any HTML-unsafe characters (
<,>,',"or&) into the result that were not already present. In
this case, you can let Django take care of all the auto-escaping
handling for you. All you need to do is set theis_safeflag toTrue
when you register your filter function, like so::text@register.filter(is_safe=True) def myfilter(value): return valueThis flag tells Django that if a "safe" string is passed into your
filter, the result will still be "safe" and if a non-safe string is
passed in, Django will automatically escape it, if necessary.You can think of this as meaning "this filter is safe -- it doesn't
introduce any possibility of unsafe HTML."The reason
is_safeis necessary is because there are plenty of
normal string operations that will turn aSafeDataobject back into
a normalstrorunicodeobject and, rather than try to catch
them all, which would be very difficult, Django repairs the damage after
the filter has completed.For example, suppose you have a filter that adds the string
xxto
the end of any input. Since this introduces no dangerous HTML characters
to the result (aside from any that were already present), you should
mark your filter withis_safe::text@register.filter(is_safe=True) def add_xx(value): return '%sxx' % valueWhen this filter is used in a template where auto-escaping is enabled,
Django will escape the output whenever the input is not already marked
as "safe".By default,
is_safeisFalse, and you can omit it from any filters
where it isn't required.Be careful when deciding if your filter really does leave safe strings
as safe. If you're removing characters, you might inadvertently leave
unbalanced HTML tags or entities in the result. For example, removing a>from the input might turn<a>into<a, which would need to
be escaped on output to avoid causing problems. Similarly, removing a
semicolon (;) can turn&into&, which is no longer a
valid entity and thus needs further escaping. Most cases won't be nearly
this tricky, but keep an eye out for any problems like that when
reviewing your code.Marking a filter
is_safewill coerce the filter's return value to
a string. If your filter should return a boolean or other non-string
value, marking itis_safewill probably have unintended
consequences (such as converting a boolean False to the string
'False').Alternatively, your filter code can manually take care of any necessary
escaping. This is necessary when you're introducing new HTML markup into
the result. You want to mark the output as safe from further
escaping so that your HTML markup isn't escaped further, so you'll need
to handle the input yourself.To mark the output as a safe string, use
:func:django.utils.safestring.mark_safe.Be careful, though. You need to do more than just mark the output as
safe. You need to ensure it really is safe, and what you do depends on
whether auto-escaping is in effect. The idea is to write filters that
can operate in templates where auto-escaping is either on or off in
order to make things easier for your template authors.In order for your filter to know the current auto-escaping state, set the
needs_autoescapeflag toTruewhen you register your filter function.
(If you don't specify this flag, it defaults toFalse). This flag tells
Django that your filter function wants to be passed an extra keyword
argument, calledautoescape, that isTrueif auto-escaping is in
effect andFalseotherwise. It is recommended to set the default of theautoescapeparameter toTrue, so that if you call the function
from Python code it will have escaping enabled by default.For example, let's write a filter that emphasizes the first character of
a string::from django import template
from django.utils.html import conditional_escape
from django.utils.safestring import mark_saferegister = template.Library()
@register.filter(needs_autoescape=True)
def initial_letter_filter(text, autoescape=True):
first, other = text[0], text[1:]
if autoescape:
esc = conditional_escape
else:
esc = lambda x: x
result = '%s%s' % (esc(first), esc(other))
return mark_safe(result)The
needs_autoescapeflag and theautoescapekeyword argument mean
that our function will know whether automatic escaping is in effect when the
filter is called. We useautoescapeto decide whether the input data
needs to be passed throughdjango.utils.html.conditional_escapeor not.
(In the latter case, we just use the identity function as the "escape"
function.) Theconditional_escape()function is likeescape()except
it only escapes input that is not aSafeDatainstance. If aSafeDatainstance is passed toconditional_escape(), the data is
returned unchanged.Finally, in the above example, we remember to mark the result as safe
so that our HTML is inserted directly into the template without further
escaping.There's no need to worry about the
is_safeflag in this case
(although including it wouldn't hurt anything). Whenever you manually
handle the auto-escaping issues and return a safe string, theis_safeflag won't change anything either way.
.. warning:: Avoiding XSS vulnerabilities when reusing built-in filters
Django's built-in filters have ``autoescape=True`` by default in order to
get the proper autoescaping behavior and avoid a cross-site script
vulnerability.
In older versions of Django, be careful when reusing Django's built-in
filters as ``autoescape`` defaults to ``None``. You'll need to pass
``autoescape=True`` to get autoescaping.
For example, if you wanted to write a custom filter called
``urlize_and_linebreaks`` that combined the :tfilter:`urlize` and
:tfilter:`linebreaksbr` filters, the filter would look like::
from django.template.defaultfilters import linebreaksbr, urlize
@register.filter(needs_autoescape=True)
def urlize_and_linebreaks(text, autoescape=True):
return linebreaksbr(
urlize(text, autoescape=autoescape),
autoescape=autoescape
)
Then:
.. code-block:: html+django
{{ comment|urlize_and_linebreaks }}
would be equivalent to:
.. code-block:: html+django
{{ comment|urlize|linebreaksbr }}.. _filters-timezones:
Filters and time zones
If you write a custom filter that operates on :class:~datetime.datetime
objects, you'll usually register it with the expects_localtime flag set toTrue::
@register.filter(expects_localtime=True)
def businesshours(value):
try:
return 9 <= value.hour < 17
except AttributeError:
return ''When this flag is set, if the first argument to your filter is a time zone
aware datetime, Django will convert it to the current time zone before passing
it to your filter when appropriate, according to :ref:rules for time zones conversions in templates <time-zones-in-templates>.
.. _howto-writing-custom-template-tags:
Writing custom template tags
Tags are more complex than filters, because tags can do anything. Django
provides a number of shortcuts that make writing most types of tags easier.
First we'll explore those shortcuts, then explain how to write a tag from
scratch for those cases when the shortcuts aren't powerful enough.
.. _howto-custom-template-tags-simple-tags:
Simple tags
.. method:: django.template.Library.simple_tag()
Many template tags take a number of arguments -- strings or template variables
-- and return a result after doing some processing based solely on
the input arguments and some external information. For example, acurrent_time tag might accept a format string and return the time as a
string formatted accordingly.
To ease the creation of these types of tags, Django provides a helper function,simple_tag. This function, which is a method ofdjango.template.Library, takes a function that accepts any number of
arguments, wraps it in a render function and the other necessary bits
mentioned above and registers it with the template system.
Our current_time function could thus be written like this::
import datetime
from django import template
register = template.Library()
@register.simple_tag
def current_time(format_string):
return datetime.datetime.now().strftime(format_string)A few things to note about the simple_tag helper function:
- Checking for the required number of arguments, etc., has already been
done by the time our function is called, so we don't need to do that. - The quotes around the argument (if any) have already been stripped away,
so we just receive a plain string. - If the argument was a template variable, our function is passed the
current value of the variable, not the variable itself.
Unlike other tag utilities, simple_tag passes its output through
:func:~django.utils.html.conditional_escape if the template context is in
autoescape mode, to ensure correct HTML and protect you from XSS
vulnerabilities.
If additional escaping is not desired, you will need to use
:func:~django.utils.safestring.mark_safe if you are absolutely sure that your
code does not contain XSS vulnerabilities. For building small HTML snippets,
use of :func:~django.utils.html.format_html instead of mark_safe() is
strongly recommended.
.. versionchanged:: 1.9
Auto-escaping for simple_tag as described in the previous two paragraphs
was added.
If your template tag needs to access the current context, you can use thetakes_context argument when registering your tag::
@register.simple_tag(takes_context=True)
def current_time(context, format_string):
timezone = context['timezone']
return your_get_current_time_method(timezone, format_string)Note that the first argument must be called context.
For more information on how the takes_context option works, see the section
on :ref:inclusion tags<howto-custom-template-tags-inclusion-tags>.
If you need to rename your tag, you can provide a custom name for it::
register.simple_tag(lambda x: x - 1, name='minusone')
@register.simple_tag(name='minustwo')
def some_function(value):
return value - 2simple_tag functions may accept any number of positional or keyword
arguments. For example::
@register.simple_tag
def my_tag(a, b, *args, **kwargs):
warning = kwargs['warning']
profile = kwargs['profile']
...
return ...Then in the template any number of arguments, separated by spaces, may be
passed to the template tag. Like in Python, the values for keyword arguments
are set using the equal sign ("=") and must be provided after the
positional arguments. For example:
.. code-block:: html+django
{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}.. versionadded:: 1.9
It's possible to store the tag results in a template variable rather than
directly outputting it. This is done by using the as argument followed by
the variable name. Doing so enables you to output the content yourself where
you see fit:
.. code-block:: html+django
{% get_current_time "%Y-%m-%d %I:%M %p" as the_time %}
<p>The time is {{ the_time }}.</p>.. _howto-custom-template-tags-inclusion-tags:
Inclusion tags
.. method:: django.template.Library.inclusion_tag()
Another common type of template tag is the type that displays some data by
rendering another template. For example, Django's admin interface uses custom
template tags to display the buttons along the bottom of the "add/change" form
pages. Those buttons always look the same, but the link targets change
depending on the object being edited -- so they're a perfect case for using a
small template that is filled with details from the current object. (In the
admin's case, this is the submit_row tag.)
These sorts of tags are called "inclusion tags".
Writing inclusion tags is probably best demonstrated by example. Let's write a
tag that outputs a list of choices for a given Poll object, such as was
created in the :ref:tutorials <creating-models>. We'll use the tag like this:
.. code-block:: html+django
{% show_results poll %}...and the output will be something like this:
.. code-block:: html
<ul>
<li>First choice</li>
<li>Second choice</li>
<li>Third choice</li>
</ul>First, define the function that takes the argument and produces a dictionary of
data for the result. The important point here is we only need to return a
dictionary, not anything more complex. This will be used as a template context
for the template fragment. Example::
def show_results(poll):
choices = poll.choice_set.all()
return {'choices': choices}Next, create the template used to render the tag's output. This template is a
fixed feature of the tag: the tag writer specifies it, not the template
designer. Following our example, the template is very simple:
.. code-block:: html+django
<ul>
{% for choice in choices %}
<li> {{ choice }} </li>
{% endfor %}
</ul>Now, create and register the inclusion tag by calling the inclusion_tag()
method on a Library object. Following our example, if the above template is
in a file called results.html in a directory that's searched by the
template loader, we'd register the tag like this::
# Here, register is a django.template.Library instance, as before
@register.inclusion_tag('results.html')
def show_results(poll):
...Alternatively it is possible to register the inclusion tag using a
:class:django.template.Template instance::
from django.template.loader import get_template
t = get_template('results.html')
register.inclusion_tag(t)(show_results)...when first creating the function.
Sometimes, your inclusion tags might require a large number of arguments,
making it a pain for template authors to pass in all the arguments and remember
their order. To solve this, Django provides a takes_context option for
inclusion tags. If you specify takes_context in creating a template tag,
the tag will have no required arguments, and the underlying Python function
will have one argument -- the template context as of when the tag was called.
For example, say you're writing an inclusion tag that will always be used in a
context that contains home_link and home_title variables that point
back to the main page. Here's what the Python function would look like::
@register.inclusion_tag('link.html', takes_context=True)
def jump_link(context):
return {
'link': context['home_link'],
'title': context['home_title'],
}Note that the first parameter to the function must be called context.
In that register.inclusion_tag() line, we specified takes_context=True
and the name of the template. Here's what the template link.html might look
like:
.. code-block:: html+django
Jump directly to <a href="{{ link }}">{{ title }}</a>.Then, any time you want to use that custom tag, load its library and call it
without any arguments, like so:
.. code-block:: html+django
{% jump_link %}Note that when you're using takes_context=True, there's no need to pass
arguments to the template tag. It automatically gets access to the context.
The takes_context parameter defaults to False. When it's set toTrue, the tag is passed the context object, as in this example. That's the
only difference between this case and the previous inclusion_tag example.
inclusion_tag functions may accept any number of positional or keyword
arguments. For example::
@register.inclusion_tag('my_template.html')
def my_tag(a, b, *args, **kwargs):
warning = kwargs['warning']
profile = kwargs['profile']
...
return ...Then in the template any number of arguments, separated by spaces, may be
passed to the template tag. Like in Python, the values for keyword arguments
are set using the equal sign ("=") and must be provided after the
positional arguments. For example:
.. code-block:: html+django
{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}Assignment tags
.. method:: django.template.Library.assignment_tag()
.. deprecated:: 1.9
``simple_tag`` can now store results in a template variable and should
be used instead.To ease the creation of tags setting a variable in the context, Django provides
a helper function, assignment_tag. This function works the same way as
:meth:~django.template.Library.simple_tag except that it stores the tag's
result in a specified context variable instead of directly outputting it.
Our earlier current_time function could thus be written like this::
@register.assignment_tag
def get_current_time(format_string):
return datetime.datetime.now().strftime(format_string)You may then store the result in a template variable using the as argument
followed by the variable name, and output it yourself where you see fit:
.. code-block:: html+django
{% get_current_time "%Y-%m-%d %I:%M %p" as the_time %}
<p>The time is {{ the_time }}.</p>Advanced custom template tags
Sometimes the basic features for custom template tag creation aren't enough.
Don't worry, Django gives you complete access to the internals required to build
a template tag from the ground up.
A quick overview
The template system works in a two-step process: compiling and rendering. To
define a custom template tag, you specify how the compilation works and how
the rendering works.
When Django compiles a template, it splits the raw template text into
''nodes''. Each node is an instance of django.template.Node and has
a render() method. A compiled template is, simply, a list of Node
objects. When you call render() on a compiled template object, the template
calls render() on each Node in its node list, with the given context.
The results are all concatenated together to form the output of the template.
Thus, to define a custom template tag, you specify how the raw template tag is
converted into a Node (the compilation function), and what the node'srender() method does.
Writing the compilation function
For each template tag the template parser encounters, it calls a Python
function with the tag contents and the parser object itself. This function is
responsible for returning a Node instance based on the contents of the tag.
For example, let's write a full implementation of our simple template tag,{% current_time %}, that displays the current date/time, formatted according
to a parameter given in the tag, in :func:~time.strftime syntax. It's a good
idea to decide the tag syntax before anything else. In our case, let's say the
tag should be used like this:
.. code-block:: html+django
<p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>The parser for this function should grab the parameter and create a Node
object::
from django import template
def do_current_time(parser, token):
try:
# split_contents() knows not to split quoted strings.
tag_name, format_string = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError(
"%r tag requires a single argument" % token.contents.split()[0]
)
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
raise template.TemplateSyntaxError(
"%r tag's argument should be in quotes" % tag_name
)
return CurrentTimeNode(format_string[1:-1])Notes:
parseris the template parser object. We don't need it in this
example.token.contentsis a string of the raw contents of the tag. In our
example, it's'current_time "%Y-%m-%d %I:%M %p"'.The
token.split_contents()method separates the arguments on spaces
while keeping quoted strings together. The more straightforwardtoken.contents.split()wouldn't be as robust, as it would naively
split on all spaces, including those within quoted strings. It's a good
idea to always usetoken.split_contents().This function is responsible for raising
django.template.TemplateSyntaxError, with helpful messages, for
any syntax error.The
TemplateSyntaxErrorexceptions use thetag_namevariable.
Don't hard-code the tag's name in your error messages, because that
couples the tag's name to your function.token.contents.split()[0]
will ''always'' be the name of your tag -- even when the tag has no
arguments.The function returns a
CurrentTimeNodewith everything the node needs
to know about this tag. In this case, it just passes the argument --"%Y-%m-%d %I:%M %p". The leading and trailing quotes from the
template tag are removed informat_string[1:-1].The parsing is very low-level. The Django developers have experimented
with writing small frameworks on top of this parsing system, using
techniques such as EBNF grammars, but those experiments made the template
engine too slow. It's low-level because that's fastest.
Writing the renderer
The second step in writing custom tags is to define a Node subclass that
has a render() method.
Continuing the above example, we need to define CurrentTimeNode::
import datetime
from django import template
class CurrentTimeNode(template.Node):
def __init__(self, format_string):
self.format_string = format_string
def render(self, context):
return datetime.datetime.now().strftime(self.format_string)Notes:
__init__()gets theformat_stringfromdo_current_time().
Always pass any options/parameters/arguments to aNodevia its__init__().The
render()method is where the work actually happens.render()should generally fail silently, particularly in a production
environment. In some cases however, particularly ifcontext.template.engine.debugisTrue, this method may raise an
exception to make debugging easier. For example, several core tags raisedjango.template.TemplateSyntaxErrorif they receive the wrong number or
type of arguments.
Ultimately, this decoupling of compilation and rendering results in an
efficient template system, because a template can render multiple contexts
without having to be parsed multiple times.
.. _tags-auto-escaping:
Auto-escaping considerations
The output from template tags is not automatically run through the
auto-escaping filters (with the exception of
:meth:~django.template.Library.simple_tag as described above). However, there
are still a couple of things you should keep in mind when writing a template
tag.
If the render() function of your template stores the result in a context
variable (rather than returning the result in a string), it should take care
to call mark_safe() if appropriate. When the variable is ultimately
rendered, it will be affected by the auto-escape setting in effect at the
time, so content that should be safe from further escaping needs to be marked
as such.
Also, if your template tag creates a new context for performing some
sub-rendering, set the auto-escape attribute to the current context's value.
The __init__ method for the Context class takes a parameter calledautoescape that you can use for this purpose. For example::
from django.template import Context
def render(self, context):
# ...
new_context = Context({'var': obj}, autoescape=context.autoescape)
# ... Do something with new_context ...This is not a very common situation, but it's useful if you're rendering a
template yourself. For example::
def render(self, context):
t = context.template.engine.get_template('small_fragment.html')
return t.render(Context({'var': obj}, autoescape=context.autoescape))If we had neglected to pass in the current context.autoescape value to our
new Context in this example, the results would have always been
automatically escaped, which may not be the desired behavior if the template
tag is used inside a :ttag:{% autoescape off %}<autoescape> block.
.. _template_tag_thread_safety:
Thread-safety considerations
Once a node is parsed, its render method may be called any number of times.
Since Django is sometimes run in multi-threaded environments, a single node may
be simultaneously rendering with different contexts in response to two separate
requests. Therefore, it's important to make sure your template tags are thread
safe.
To make sure your template tags are thread safe, you should never store state
information on the node itself. For example, Django provides a builtin
:ttag:cycle template tag that cycles among a list of given strings each time
it's rendered:
.. code-block:: html+django
{% for o in some_list %}
<tr class="{% cycle 'row1' 'row2' %}">
...
</tr>
{% endfor %}A naive implementation of CycleNode might look something like this::
import itertools
from django import template
class CycleNode(template.Node):
def __init__(self, cyclevars):
self.cycle_iter = itertools.cycle(cyclevars)
def render(self, context):
return next(self.cycle_iter)But, suppose we have two templates rendering the template snippet from above at
the same time:
- Thread 1 performs its first loop iteration,
CycleNode.render()
returns 'row1' - Thread 2 performs its first loop iteration,
CycleNode.render()
returns 'row2' - Thread 1 performs its second loop iteration,
CycleNode.render()
returns 'row1' - Thread 2 performs its second loop iteration,
CycleNode.render()
returns 'row2'
The CycleNode is iterating, but it's iterating globally. As far as Thread 1
and Thread 2 are concerned, it's always returning the same value. This is
obviously not what we want!
To address this problem, Django provides a render_context that's associated
with the context of the template that is currently being rendered. Therender_context behaves like a Python dictionary, and should be used to
store Node state between invocations of the render method.
Let's refactor our CycleNode implementation to use the render_context::
class CycleNode(template.Node):
def __init__(self, cyclevars):
self.cyclevars = cyclevars
def render(self, context):
if self not in context.render_context:
context.render_context[self] = itertools.cycle(self.cyclevars)
cycle_iter = context.render_context[self]
return next(cycle_iter)Note that it's perfectly safe to store global information that will not change
throughout the life of the Node as an attribute. In the case ofCycleNode, the cyclevars argument doesn't change after the Node is
instantiated, so we don't need to put it in the render_context. But state
information that is specific to the template that is currently being rendered,
like the current iteration of the CycleNode, should be stored in therender_context.
.. note::
Notice how we used self to scope the CycleNode specific information
within the render_context. There may be multiple CycleNodes in a
given template, so we need to be careful not to clobber another node's
state information. The easiest way to do this is to always use self as
the key into render_context. If you're keeping track of several state
variables, make render_context[self] a dictionary.
Registering the tag
Finally, register the tag with your module's Library instance, as explained
in :ref:writing custom template filters<howto-writing-custom-template-tags>
above. Example::
register.tag('current_time', do_current_time)The tag() method takes two arguments:
- The name of the template tag -- a string. If this is left out, the
name of the compilation function will be used. - The compilation function -- a Python function (not the name of the
function as a string).
As with filter registration, it is also possible to use this as a decorator::
@register.tag(name="current_time")
def do_current_time(parser, token):
...
@register.tag
def shout(parser, token):
...If you leave off the name argument, as in the second example above, Django
will use the function's name as the tag name.
Passing template variables to the tag
Although you can pass any number of arguments to a template tag usingtoken.split_contents(), the arguments are all unpacked as
string literals. A little more work is required in order to pass dynamic
content (a template variable) to a template tag as an argument.
While the previous examples have formatted the current time into a string and
returned the string, suppose you wanted to pass in a
:class:~django.db.models.DateTimeField from an object and have the template
tag format that date-time:
.. code-block:: html+django
<p>This post was last updated at {% format_time blog_entry.date_updated "%Y-%m-%d %I:%M %p" %}.</p>Initially, token.split_contents() will return three values:
- The tag name
format_time. - The string
'blog_entry.date_updated'(without the surrounding
quotes). - The formatting string
'"%Y-%m-%d %I:%M %p"'. The return value fromsplit_contents()will include the leading and trailing quotes for
string literals like this.
Now your tag should begin to look like this::
from django import template
def do_format_time(parser, token):
try:
# split_contents() knows not to split quoted strings.
tag_name, date_to_be_formatted, format_string = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError(
"%r tag requires exactly two arguments" % token.contents.split()[0]
)
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
raise template.TemplateSyntaxError(
"%r tag's argument should be in quotes" % tag_name
)
return FormatTimeNode(date_to_be_formatted, format_string[1:-1])You also have to change the renderer to retrieve the actual contents of thedate_updated property of the blog_entry object. This can be
accomplished by using the Variable() class in django.template.
To use the Variable class, simply instantiate it with the name of the
variable to be resolved, and then call variable.resolve(context). So,
for example::
class FormatTimeNode(template.Node):
def __init__(self, date_to_be_formatted, format_string):
self.date_to_be_formatted = template.Variable(date_to_be_formatted)
self.format_string = format_string
def render(self, context):
try:
actual_date = self.date_to_be_formatted.resolve(context)
return actual_date.strftime(self.format_string)
except template.VariableDoesNotExist:
return ''Variable resolution will throw a VariableDoesNotExist exception if it
cannot resolve the string passed to it in the current context of the page.
Setting a variable in the context
The above examples simply output a value. Generally, it's more flexible if your
template tags set template variables instead of outputting values. That way,
template authors can reuse the values that your template tags create.
To set a variable in the context, just use dictionary assignment on the context
object in the render() method. Here's an updated version ofCurrentTimeNode that sets a template variable current_time instead of
outputting it::
import datetime
from django import template
class CurrentTimeNode2(template.Node):
def __init__(self, format_string):
self.format_string = format_string
def render(self, context):
context['current_time'] = datetime.datetime.now().strftime(self.format_string)
return ''Note that render() returns the empty string. render() should always
return string output. If all the template tag does is set a variable,render() should return the empty string.
Here's how you'd use this new version of the tag:
.. code-block:: html+django
{% current_time "%Y-%M-%d %I:%M %p" %}<p>The time is {{ current_time }}.</p>.. admonition:: Variable scope in context
Any variable set in the context will only be available in the same
``block`` of the template in which it was assigned. This behavior is
intentional; it provides a scope for variables so that they don't conflict
with context in other blocks.But, there's a problem with CurrentTimeNode2: The variable namecurrent_time is hard-coded. This means you'll need to make sure your
template doesn't use {{ current_time }} anywhere else, because the{% current_time %} will blindly overwrite that variable's value. A cleaner
solution is to make the template tag specify the name of the output variable,
like so:
.. code-block:: html+django
{% current_time "%Y-%M-%d %I:%M %p" as my_current_time %}
<p>The current time is {{ my_current_time }}.</p>To do that, you'll need to refactor both the compilation function and Node
class, like so::
import re
class CurrentTimeNode3(template.Node):
def __init__(self, format_string, var_name):
self.format_string = format_string
self.var_name = var_name
def render(self, context):
context[self.var_name] = datetime.datetime.now().strftime(self.format_string)
return ''
def do_current_time(parser, token):
# This version uses a regular expression to parse tag contents.
try:
# Splitting by None == splitting by spaces.
tag_name, arg = token.contents.split(None, 1)
except ValueError:
raise template.TemplateSyntaxError(
"%r tag requires arguments" % token.contents.split()[0]
)
m = re.search(r'(.*?) as (\w+)', arg)
if not m:
raise template.TemplateSyntaxError("%r tag had invalid arguments" % tag_name)
format_string, var_name = m.groups()
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
raise template.TemplateSyntaxError(
"%r tag's argument should be in quotes" % tag_name
)
return CurrentTimeNode3(format_string[1:-1], var_name)The difference here is that do_current_time() grabs the format string and
the variable name, passing both to CurrentTimeNode3.
Finally, if you only need to have a simple syntax for your custom
context-updating template tag, consider using the
:meth:~django.template.Library.simple_tag shortcut, which supports assigning
the tag results to a template variable.
Parsing until another block tag
Template tags can work in tandem. For instance, the standard
:ttag:{% comment %}<comment> tag hides everything until {% endcomment %}.
To create a template tag such as this, use parser.parse() in your
compilation function.
Here's how a simplified {% comment %} tag might be implemented::
def do_comment(parser, token):
nodelist = parser.parse(('endcomment',))
parser.delete_first_token()
return CommentNode()
class CommentNode(template.Node):
def render(self, context):
return ''.. note::
The actual implementation of :ttag:{% comment %}<comment> is slightly
different in that it allows broken template tags to appear between
{% comment %} and {% endcomment %}. It does so by calling
parser.skip_past('endcomment') instead of parser.parse(('endcomment',))
followed by parser.delete_first_token(), thus avoiding the generation of a
node list.
parser.parse() takes a tuple of names of block tags ''to parse until''. It
returns an instance of django.template.NodeList, which is a list of
all Node objects that the parser encountered ''before'' it encountered
any of the tags named in the tuple.
In "nodelist = parser.parse(('endcomment',))" in the above example,nodelist is a list of all nodes between the {% comment %} and{% endcomment %}, not counting {% comment %} and {% endcomment %}
themselves.
After parser.parse() is called, the parser hasn't yet "consumed" the{% endcomment %} tag, so the code needs to explicitly callparser.delete_first_token().
CommentNode.render() simply returns an empty string. Anything between{% comment %} and {% endcomment %} is ignored.
Parsing until another block tag, and saving contents
In the previous example, do_comment() discarded everything between{% comment %} and {% endcomment %}. Instead of doing that, it's
possible to do something with the code between block tags.
For example, here's a custom template tag, {% upper %}, that capitalizes
everything between itself and {% endupper %}.
Usage:
.. code-block:: html+django
{% upper %}This will appear in uppercase, {{ your_name }}.{% endupper %}As in the previous example, we'll use parser.parse(). But this time, we
pass the resulting nodelist to the Node::
def do_upper(parser, token):
nodelist = parser.parse(('endupper',))
parser.delete_first_token()
return UpperNode(nodelist)
class UpperNode(template.Node):
def __init__(self, nodelist):
self.nodelist = nodelist
def render(self, context):
output = self.nodelist.render(context)
return output.upper()The only new concept here is the self.nodelist.render(context) inUpperNode.render().
For more examples of complex rendering, see the source code of
:ttag:{% for %}<for> in django/template/defaulttags.py and
:ttag:{% if %}<if> in django/template/smartif.py.
大一小学期 Week 3 Python Exam 2016 Docs Howto Error Reporting (`大一小学期/Week_3-Python/exam/2016/docs/howto/error-reporting.txt`)
=============== Error reporting
When you're running a public site you should always turn off the
:setting:DEBUG setting. That will make your server run much faster, and will
also prevent malicious users from seeing details of your application that can be
revealed by the error pages.
However, running with :setting:DEBUG set to False means you'll never see
errors generated by your site -- everyone will just see your public error pages.
You need to keep track of errors that occur in deployed sites, so Django can be
configured to create reports with details about those errors.
Email reports
Server errors
When :setting:DEBUG is False, Django will email the users listed in the
:setting:ADMINS setting whenever your code raises an unhandled exception and
results in an internal server error (HTTP status code 500). This gives the
administrators immediate notification of any errors. The :setting:ADMINS will
get a description of the error, a complete Python traceback, and details about
the HTTP request that caused the error.
.. note::
In order to send email, Django requires a few settings telling it
how to connect to your mail server. At the very least, you'll need
to specify :setting:EMAIL_HOST and possibly
:setting:EMAIL_HOST_USER and :setting:EMAIL_HOST_PASSWORD,
though other settings may be also required depending on your mail
server's configuration. Consult :doc:the Django settings documentation </ref/settings> for a full list of email-related
settings.
By default, Django will send email from root@localhost. However, some mail
providers reject all email from this address. To use a different sender
address, modify the :setting:SERVER_EMAIL setting.
To activate this behavior, put the email addresses of the recipients in the
:setting:ADMINS setting.
.. seealso::
Server error emails are sent using the logging framework, so you can
customize this behavior by :doc:`customizing your logging configuration
</topics/logging>`.404 errors
Django can also be configured to email errors about broken links (404 "page
not found" errors). Django sends emails about 404 errors when:
:setting:
DEBUGisFalse;Your :setting:
MIDDLEWAREsetting includes
:class:django.middleware.common.BrokenLinkEmailsMiddleware.
If those conditions are met, Django will email the users listed in the
:setting:MANAGERS setting whenever your code raises a 404 and the request has
a referer. It doesn't bother to email for 404s that don't have a referer --
those are usually just people typing in broken URLs or broken Web bots. It also
ignores 404s when the referer is equal to the requested URL, since this
behavior is from broken Web bots too.
.. versionchanged:: 1.9
In older versions, 404s were not ignored when the referer was equal to the
requested URL... note::
:class:`~django.middleware.common.BrokenLinkEmailsMiddleware` must appear
before other middleware that intercepts 404 errors, such as
:class:`~django.middleware.locale.LocaleMiddleware` or
:class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware`.
Put it towards the top of your :setting:`MIDDLEWARE` setting.You can tell Django to stop reporting particular 404s by tweaking the
:setting:IGNORABLE_404_URLS setting. It should be a list of compiled
regular expression objects. For example::
import re
IGNORABLE_404_URLS = [
re.compile(r'\.(php|cgi)$'),
re.compile(r'^/phpmyadmin/'),
]In this example, a 404 to any URL ending with .php or .cgi will not be
reported. Neither will any URL starting with /phpmyadmin/.
The following example shows how to exclude some conventional URLs that browsers and
crawlers often request::
import re
IGNORABLE_404_URLS = [
re.compile(r'^/apple-touch-icon.*\.png$'),
re.compile(r'^/favicon\.ico$'),
re.compile(r'^/robots\.txt$'),
](Note that these are regular expressions, so we put a backslash in front of
periods to escape them.)
If you'd like to customize the behavior of
:class:django.middleware.common.BrokenLinkEmailsMiddleware further (for
example to ignore requests coming from web crawlers), you should subclass it
and override its methods.
.. seealso::
404 errors are logged using the logging framework. By default, these log
records are ignored, but you can use them for error reporting by writing a
handler and :doc:`configuring logging </topics/logging>` appropriately... _filtering-error-reports:
Filtering error reports
.. warning::
Filtering sensitive data is a hard problem, and it's nearly impossible to
guarantee that sensitive won't leak into an error report. Therefore, error
reports should only be available to trusted team members and you should
avoid transmitting error reports unencrypted over the Internet (such as
through email).Filtering sensitive information
.. currentmodule:: django.views.decorators.debug
Error reports are really helpful for debugging errors, so it is generally
useful to record as much relevant information about those errors as possible.
For example, by default Django records the full traceback_ for the
exception raised, each traceback frame_’s local variables, and the
:class:~django.http.HttpRequest’s :ref:attributes<httprequest-attributes>.
However, sometimes certain types of information may be too sensitive and thus
may not be appropriate to be kept track of, for example a user's password or
credit card number. So in addition to filtering out settings that appear to be
sensitive as described in the :setting:DEBUG documentation, Django offers a
set of function decorators to help you control which information should be
filtered out of error reports in a production environment (that is, where
:setting:DEBUG is set to False): :func:sensitive_variables and
:func:sensitive_post_parameters.
.. _full traceback: https://en.wikipedia.org/wiki/Stack_trace
.. _traceback frame: https://en.wikipedia.org/wiki/Stack_frame
.. function:: sensitive_variables(*variables)
If a function (either a view or any regular callback) in your code uses
local variables susceptible to contain sensitive information, you may
prevent the values of those variables from being included in error reports
using the ``sensitive_variables`` decorator::
from django.views.decorators.debug import sensitive_variables
@sensitive_variables('user', 'pw', 'cc')
def process_info(user):
pw = user.pass_word
cc = user.credit_card_number
name = user.name
...
In the above example, the values for the ``user``, ``pw`` and ``cc``
variables will be hidden and replaced with stars (`**********`) in the
error reports, whereas the value of the ``name`` variable will be
disclosed.
To systematically hide all local variables of a function from error logs,
do not provide any argument to the ``sensitive_variables`` decorator::
@sensitive_variables()
def my_function():
...
.. admonition:: When using multiple decorators
If the variable you want to hide is also a function argument (e.g.
'``user``’ in the following example), and if the decorated function has
multiple decorators, then make sure to place ``@sensitive_variables``
at the top of the decorator chain. This way it will also hide the
function argument as it gets passed through the other decorators::
@sensitive_variables('user', 'pw', 'cc')
@some_decorator
@another_decorator
def process_info(user):
..... function:: sensitive_post_parameters(*parameters)
If one of your views receives an :class:`~django.http.HttpRequest` object
with :attr:`POST parameters<django.http.HttpRequest.POST>` susceptible to
contain sensitive information, you may prevent the values of those
parameters from being included in the error reports using the
``sensitive_post_parameters`` decorator::
from django.views.decorators.debug import sensitive_post_parameters
@sensitive_post_parameters('pass_word', 'credit_card_number')
def record_user_profile(request):
UserProfile.create(
user=request.user,
password=request.POST['pass_word'],
credit_card=request.POST['credit_card_number'],
name=request.POST['name'],
)
...
In the above example, the values for the ``pass_word`` and
``credit_card_number`` POST parameters will be hidden and replaced with
stars (`**********`) in the request's representation inside the error
reports, whereas the value of the ``name`` parameter will be disclosed.
To systematically hide all POST parameters of a request in error reports,
do not provide any argument to the ``sensitive_post_parameters`` decorator::
@sensitive_post_parameters()
def my_view(request):
...
All POST parameters are systematically filtered out of error reports for
certain :mod:`django.contrib.auth.views` views (``login``,
``password_reset_confirm``, ``password_change``, and ``add_view`` and
``user_change_password`` in the ``auth`` admin) to prevent the leaking of
sensitive information such as user passwords... _custom-error-reports:
Custom error reports
All :func:sensitive_variables and :func:sensitive_post_parameters do is,
respectively, annotate the decorated function with the names of sensitive
variables and annotate the HttpRequest object with the names of sensitive
POST parameters, so that this sensitive information can later be filtered out
of reports when an error occurs. The actual filtering is done by Django's
default error reporter filter:
:class:django.views.debug.SafeExceptionReporterFilter. This filter uses the
decorators' annotations to replace the corresponding values with stars
(**********) when the error reports are produced. If you wish to override or
customize this default behavior for your entire site, you need to define your
own filter class and tell Django to use it via the
:setting:DEFAULT_EXCEPTION_REPORTER_FILTER setting::
DEFAULT_EXCEPTION_REPORTER_FILTER = 'path.to.your.CustomExceptionReporterFilter'You may also control in a more granular way which filter to use within any
given view by setting the HttpRequest’s exception_reporter_filter
attribute::
def my_view(request):
if request.user.is_authenticated:
request.exception_reporter_filter = CustomExceptionReporterFilter()
..... currentmodule:: django.views.debug
Your custom filter class needs to inherit from
:class:django.views.debug.SafeExceptionReporterFilter and may override the
following methods:
.. class:: SafeExceptionReporterFilter
.. method:: SafeExceptionReporterFilter.is_active(request)
Returns ``True`` to activate the filtering operated in the other methods.
By default the filter is active if :setting:`DEBUG` is ``False``... method:: SafeExceptionReporterFilter.get_post_parameters(request)
Returns the filtered dictionary of POST parameters. By default it replaces
the values of sensitive parameters with stars (`**********`)... method:: SafeExceptionReporterFilter.get_traceback_frame_variables(request, tb_frame)
Returns the filtered dictionary of local variables for the given traceback
frame. By default it replaces the values of sensitive variables with stars
(`**********`)... seealso::
You can also set up custom error reporting by writing a custom piece of
:ref:`exception middleware <exception-middleware>`. If you do write custom
error handling, it's a good idea to emulate Django's built-in error handling
and only report/log errors if :setting:`DEBUG` is ``False``.大一小学期 Week 3 Python Exam 2016 Docs Howto Index (`大一小学期/Week_3-Python/exam/2016/docs/howto/index.txt`)
=============== "How-to" guides
Here you'll find short answers to "How do I....?" types of questions. These
how-to guides don't cover topics in depth -- you'll find that material in the
:doc:/topics/index and the :doc:/ref/index. However, these guides will help
you quickly accomplish common tasks.
.. toctree::
:maxdepth: 1
auth-remote-user
custom-management-commands
custom-model-fields
custom-lookups
custom-template-tags
custom-file-storage
deployment/index
upgrade-version
error-reporting
initial-data
jython
legacy-databases
outputting-csv
outputting-pdf
static-files/index
static-files/deployment
windows
writing-migrations
.. seealso::
The `Django community aggregator`_, where we aggregate content from the
global Django community. Many writers in the aggregator write this sort of
how-to material.
.. _django community aggregator: https://www.djangoproject.com/community/大一小学期 Week 3 Python Exam 2016 Docs Howto Initial Data (`大一小学期/Week_3-Python/exam/2016/docs/howto/initial-data.txt`)
================================= Providing initial data for models
It's sometimes useful to pre-populate your database with hard-coded data when
you're first setting up an app. You can provide initial data via fixtures.
.. _initial-data-via-fixtures:
Providing initial data with fixtures
A fixture is a collection of data that Django knows how to import into a
database. The most straightforward way of creating a fixture if you've already
got some data is to use the :djadmin:manage.py dumpdata <dumpdata> command.
Or, you can write fixtures by hand; fixtures can be written as JSON, XML or YAML
(with PyYAML_ installed) documents. The :doc:serialization documentation </topics/serialization> has more details about each of these supported
:ref:serialization formats <serialization-formats>.
.. _PyYAML: http://www.pyyaml.org/
As an example, though, here's what a fixture for a simple Person model might
look like in JSON:
.. code-block:: js
[
{
"model": "myapp.person",
"pk": 1,
"fields": {
"first_name": "John",
"last_name": "Lennon"
}
},
{
"model": "myapp.person",
"pk": 2,
"fields": {
"first_name": "Paul",
"last_name": "McCartney"
}
}
]And here's that same fixture as YAML:
.. code-block:: none
- model: myapp.person
pk: 1
fields:
first_name: John
last_name: Lennon
- model: myapp.person
pk: 2
fields:
first_name: Paul
last_name: McCartneyYou'll store this data in a fixtures directory inside your app.
Loading data is easy: just call :djadmin:manage.py loaddata <loaddata><fixturename>, where <fixturename> is the name of the fixture file
you've created. Each time you run :djadmin:loaddata, the data will be read
from the fixture and re-loaded into the database. Note this means that if you
change one of the rows created by a fixture and then run :djadmin:loaddata
again, you'll wipe out any changes you've made.
Where Django finds fixture files
By default, Django looks in the fixtures directory inside each app for
fixtures. You can set the :setting:FIXTURE_DIRS setting to a list of
additional directories where Django should look.
When running :djadmin:manage.py loaddata <loaddata>, you can also
specify a path to a fixture file, which overrides searching the usual
directories.
.. seealso::
Fixtures are also used by the :ref:`testing framework
<topics-testing-fixtures>` to help set up a consistent test environment.大一小学期 Week 3 Python Exam 2016 Docs Howto Jython (`大一小学期/Week_3-Python/exam/2016/docs/howto/jython.txt`)
======================== Running Django on Jython
.. index:: Jython, Java, JVM
Jython_ is an implementation of Python that runs on the Java platform (JVM).
This document will get you up and running with Django on top of Jython.
Installing Jython
Django works with Jython versions 2.7b2 and higher. See the Jython_ website for
download and installation instructions.
.. _jython: http://www.jython.org/
Creating a servlet container
If you just want to experiment with Django, skip ahead to the next section;
Django includes a lightweight Web server you can use for testing, so you won't
need to set up anything else until you're ready to deploy Django in production.
If you want to use Django on a production site, use a Java servlet container,
such as Apache Tomcat. Full JavaEE applications servers such as GlassFish
or JBoss_ are also OK, if you need the extra features they include.
.. _Apache Tomcat: https://tomcat.apache.org/
.. _GlassFish: https://glassfish.java.net/
.. _JBoss: https://www.jboss.org/
Installing Django
The next step is to install Django itself. This is exactly the same as
installing Django on standard Python, so see
:ref:removing-old-versions-of-django and :ref:install-django-code for
instructions.
Installing Jython platform support libraries
The django-jython_ project contains database backends and management commands
for Django/Jython development. Note that the builtin Django backends won't work
on top of Jython.
.. _django-jython: https://github.com/beachmachine/django-jython
To install it, follow the installation instructions_ detailed on the project
website. Also, read the database backends_ documentation there.
.. _installation instructions: https://pythonhosted.org/django-jython/quickstart.html#install
.. _database backends: https://pythonhosted.org/django-jython/database-backends.html
Differences with Django on Jython
.. index:: JYTHONPATH
At this point, Django on Jython should behave nearly identically to Django
running on standard Python. However, are a few differences to keep in mind:
Remember to use the
jythoncommand instead ofpython. The
documentation usespythonfor consistency, but if you're using Jython
you'll want to mentally replacepythonwithjythonevery time it
occurs.Similarly, you'll need to use the
JYTHONPATHenvironment variable
instead ofPYTHONPATH.Any part of Django that requires
Pillow_ will not work.
.. _Pillow: https://pillow.readthedocs.io/en/latest/
大一小学期 Week 3 Python Exam 2016 Docs Howto Legacy Databases (`大一小学期/Week_3-Python/exam/2016/docs/howto/legacy-databases.txt`)
========================================= Integrating Django with a legacy database
While Django is best suited for developing new applications, it's quite
possible to integrate it into legacy databases. Django includes a couple of
utilities to automate as much of this process as possible.
This document assumes you know the Django basics, as covered in the
:doc:tutorial </intro/tutorial01>.
Once you've got Django set up, you'll follow this general process to integrate
with an existing database.
Give Django your database parameters
You'll need to tell Django what your database connection parameters are, and
what the name of the database is. Do that by editing the :setting:DATABASES
setting and assigning values to the following keys for the 'default'
connection:
- :setting:
NAME - :setting:
ENGINE <DATABASE-ENGINE> - :setting:
USER - :setting:
PASSWORD - :setting:
HOST - :setting:
PORT
Auto-generate the models
.. highlight:: bash
Django comes with a utility called :djadmin:inspectdb that can create models
by introspecting an existing database. You can view the output by running this
command::
$ python manage.py inspectdbSave this as a file by using standard Unix output redirection::
$ python manage.py inspectdb > models.pyThis feature is meant as a shortcut, not as definitive model generation. See the
:djadmin:documentation of inspectdb <inspectdb> for more information.
Once you've cleaned up your models, name the file models.py and put it in
the Python package that holds your app. Then add the app to your
:setting:INSTALLED_APPS setting.
By default, :djadmin:inspectdb creates unmanaged models. That is,managed = False in the model's Meta class tells Django not to manage
each table's creation, modification, and deletion::
class Person(models.Model):
id = models.IntegerField(primary_key=True)
first_name = models.CharField(max_length=70)
class Meta:
managed = False
db_table = 'CENSUS_PERSONS'If you do want to allow Django to manage the table's lifecycle, you'll need to
change the :attr:~django.db.models.Options.managed option above to True
(or simply remove it because True is its default value).
Install the core Django tables
Next, run the :djadmin:migrate command to install any extra needed database
records such as admin permissions and content types::
$ python manage.py migrateTest and tweak
Those are the basic steps -- from here you'll want to tweak the models Django
generated until they work the way you'd like. Try accessing your data via the
Django database API, and try editing objects via Django's admin site, and edit
the models file accordingly.
大一小学期 Week 3 Python Exam 2016 Docs Howto Outputting Csv (`大一小学期/Week_3-Python/exam/2016/docs/howto/outputting-csv.txt`)
========================== Outputting CSV with Django
This document explains how to output CSV (Comma Separated Values) dynamically
using Django views. To do this, you can either use the Python CSV library or the
Django template system.
Using the Python CSV library
Python comes with a CSV library, :mod:csv. The key to using it with Django is
that the :mod:csv module's CSV-creation capability acts on file-like objects,
and Django's :class:~django.http.HttpResponse objects are file-like objects.
Here's an example::
import csv
from django.http import HttpResponse
def some_view(request):
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
writer = csv.writer(response)
writer.writerow(['First row', 'Foo', 'Bar', 'Baz'])
writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"])
return responseThe code and comments should be self-explanatory, but a few things deserve a
mention:
The response gets a special MIME type, :mimetype:
text/csv. This tells
browsers that the document is a CSV file, rather than an HTML file. If
you leave this off, browsers will probably interpret the output as HTML,
which will result in ugly, scary gobbledygook in the browser window.The response gets an additional
Content-Dispositionheader, which
contains the name of the CSV file. This filename is arbitrary; call it
whatever you want. It'll be used by browsers in the "Save as..." dialog, etc.Hooking into the CSV-generation API is easy: Just pass
responseas the
first argument tocsv.writer. Thecsv.writerfunction expects a
file-like object, and :class:~django.http.HttpResponseobjects fit the
bill.For each row in your CSV file, call
writer.writerow, passing it an
iterable object such as a list or tuple.The CSV module takes care of quoting for you, so you don't have to worry
about escaping strings with quotes or commas in them. Just passwriterow()your raw strings, and it'll do the right thing.
.. admonition:: Handling Unicode on Python 2
Python 2's :mod:`csv` module does not support Unicode input. Since Django
uses Unicode internally this means strings read from sources such as
:class:`~django.http.HttpRequest` are potentially problematic. There are a
few options for handling this:
* Manually encode all Unicode objects to a compatible encoding.
* Use the ``UnicodeWriter`` class provided in the `csv module's examples
section`_.
* Use the `python-unicodecsv module`_, which aims to be a drop-in
replacement for :mod:`csv` that gracefully handles Unicode.
For more information, see the Python documentation of the :mod:`csv` module.
.. _`csv module's examples section`: https://docs.python.org/2/library/csv.html#examples
.. _`python-unicodecsv module`: https://github.com/jdunck/python-unicodecsv.. _streaming-csv-files:
Streaming large CSV files
When dealing with views that generate very large responses, you might want to
consider using Django's :class:~django.http.StreamingHttpResponse instead.
For example, by streaming a file that takes a long time to generate you can
avoid a load balancer dropping a connection that might have otherwise timed out
while the server was generating the response.
In this example, we make full use of Python generators to efficiently handle
the assembly and transmission of a large CSV file::
import csv
from django.utils.six.moves import range
from django.http import StreamingHttpResponse
class Echo(object):
"""An object that implements just the write method of the file-like
interface.
"""
def write(self, value):
"""Write the value by returning it, instead of storing in a buffer."""
return value
def some_streaming_csv_view(request):
"""A view that streams a large CSV file."""
# Generate a sequence of rows. The range is based on the maximum number of
# rows that can be handled by a single sheet in most spreadsheet
# applications.
rows = (["Row {}".format(idx), str(idx)] for idx in range(65536))
pseudo_buffer = Echo()
writer = csv.writer(pseudo_buffer)
response = StreamingHttpResponse((writer.writerow(row) for row in rows),
content_type="text/csv")
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
return responseUsing the template system
Alternatively, you can use the :doc:Django template system </topics/templates>
to generate CSV. This is lower-level than using the convenient Python :mod:csv
module, but the solution is presented here for completeness.
The idea here is to pass a list of items to your template, and have the
template output the commas in a :ttag:for loop.
Here's an example, which generates the same CSV file as above::
from django.http import HttpResponse
from django.template import loader, Context
def some_view(request):
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
# The data is hard-coded here, but you could load it from a database or
# some other source.
csv_data = (
('First row', 'Foo', 'Bar', 'Baz'),
('Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"),
)
t = loader.get_template('my_template_name.txt')
c = Context({
'data': csv_data,
})
response.write(t.render(c))
return responseThe only difference between this example and the previous example is that this
one uses template loading instead of the CSV module. The rest of the code --
such as the content_type='text/csv' -- is the same.
Then, create the template my_template_name.txt, with this template code:
.. code-block:: html+django
{% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
{% endfor %}This template is quite basic. It just iterates over the given data and displays
a line of CSV for each row. It uses the :tfilter:addslashes template filter to
ensure there aren't any problems with quotes.
Other text-based formats
Notice that there isn't very much specific to CSV here -- just the specific
output format. You can use either of these techniques to output any text-based
format you can dream of. You can also use a similar technique to generate
arbitrary binary data; see :doc:/howto/outputting-pdf for an example.
大一小学期 Week 3 Python Exam 2016 Docs Howto Outputting Pdf (`大一小学期/Week_3-Python/exam/2016/docs/howto/outputting-pdf.txt`)
=========================== Outputting PDFs with Django
This document explains how to output PDF files dynamically using Django views.
This is made possible by the excellent, open-source ReportLab_ Python PDF
library.
The advantage of generating PDF files dynamically is that you can create
customized PDFs for different purposes -- say, for different users or different
pieces of content.
For example, Django was used at kusports.com_ to generate customized,
printer-friendly NCAA tournament brackets, as PDF files, for people
participating in a March Madness contest.
.. _ReportLab: http://www.reportlab.com/opensource/
.. _kusports.com: http://www.kusports.com/
Install ReportLab
The ReportLab library is available on PyPI. A user guide (not
coincidentally, a PDF file) is also available for download.
You can install ReportLab with pip:
.. code-block:: console
$ pip install reportlabTest your installation by importing it in the Python interactive interpreter::
>>> import reportlabIf that command doesn't raise any errors, the installation worked.
.. _available on PyPI: https://pypi.python.org/pypi/reportlab
.. _user guide: http://www.reportlab.com/docs/reportlab-userguide.pdf
Write your view
The key to generating PDFs dynamically with Django is that the ReportLab API
acts on file-like objects, and Django's :class:~django.http.HttpResponse
objects are file-like objects.
Here's a "Hello World" example::
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def some_view(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
# Create the PDF object, using the response object as its "file."
p = canvas.Canvas(response)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly, and we're done.
p.showPage()
p.save()
return responseThe code and comments should be self-explanatory, but a few things deserve a
mention:
The response gets a special MIME type, :mimetype:
application/pdf. This
tells browsers that the document is a PDF file, rather than an HTML file.
If you leave this off, browsers will probably interpret the output as
HTML, which would result in ugly, scary gobbledygook in the browser
window.The response gets an additional
Content-Dispositionheader, which
contains the name of the PDF file. This filename is arbitrary: Call it
whatever you want. It'll be used by browsers in the "Save as..." dialog, etc.The
Content-Dispositionheader starts with'attachment; 'in this
example. This forces Web browsers to pop-up a dialog box
prompting/confirming how to handle the document even if a default is set
on the machine. If you leave off'attachment;', browsers will handle
the PDF using whatever program/plugin they've been configured to use for
PDFs. Here's what that code would look like::textresponse['Content-Disposition'] = 'filename="somefilename.pdf"'Hooking into the ReportLab API is easy: Just pass
responseas the
first argument tocanvas.Canvas. TheCanvasclass expects a
file-like object, and :class:~django.http.HttpResponseobjects fit the
bill.Note that all subsequent PDF-generation methods are called on the PDF
object (in this case,p) -- not onresponse.Finally, it's important to call
showPage()andsave()on the PDF
file.
.. note::
ReportLab is not thread-safe. Some of our users have reported odd issues
with building PDF-generating Django views that are accessed by many people
at the same time.Complex PDFs
If you're creating a complex PDF document with ReportLab, consider using the
:mod:io library as a temporary holding place for your PDF file. This
library provides a file-like object interface that is particularly efficient.
Here's the above "Hello World" example rewritten to use :mod:io::
from io import BytesIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def some_view(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
buffer = BytesIO()
# Create the PDF object, using the BytesIO object as its "file."
p = canvas.Canvas(buffer)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly.
p.showPage()
p.save()
# Get the value of the BytesIO buffer and write it to the response.
pdf = buffer.getvalue()
buffer.close()
response.write(pdf)
return responseFurther resources
- PDFlib_ is another PDF-generation library that has Python bindings. To
use it with Django, just use the same concepts explained in this article. XHTML2PDF_ is yet another PDF-generation library. It ships with an example
of how to integrate it with Django.- HTMLdoc_ is a command-line script that can convert HTML to PDF. It
doesn't have a Python interface, but you can escape out to the shell
usingsystemorpopenand retrieve the output in Python.
.. _PDFlib: http://www.pdflib.org/
.. _XHTML2PDF: https://github.com/xhtml2pdf/xhtml2pdf
.. _HTMLdoc: https://www.msweet.org/projects.php?Z1
Other formats
Notice that there isn't a lot in these examples that's PDF-specific -- just the
bits using reportlab. You can use a similar technique to generate any
arbitrary format that you can find a Python library for. Also see
:doc:/howto/outputting-csv for another example and some techniques you can use
when generated text-based formats.
大一小学期 Week 3 Python Exam 2016 Docs Howto Upgrade Version (`大一小学期/Week_3-Python/exam/2016/docs/howto/upgrade-version.txt`)
=================================== Upgrading Django to a newer version
While it can be a complex process at times, upgrading to the latest Django
version has several benefits:
- New features and improvements are added.
- Bugs are fixed.
- Older version of Django will eventually no longer receive security updates.
(see :ref:backwards-compatibility-policy). - Upgrading as each new Django release is available makes future upgrades less
painful by keeping your code base up to date.
Here are some things to consider to help make your upgrade process as smooth as
possible.
Required Reading
If it's your first time doing an upgrade, it is useful to read the :doc:guide on the different release processes </internals/release-process>.
Afterwards, you should familiarize yourself with the changes that were made in
the new Django version(s):
- Read the :doc:
release notes </releases/index>for each 'final' release from
the one after your current Django version, up to and including the version to
which you plan to upgrade. - Look at the :doc:
deprecation timeline</internals/deprecation>for the
relevant versions.
Pay particular attention to backwards incompatible changes to get a clear idea
of what will be needed for a successful upgrade.
Dependencies
In most cases it will be necessary to upgrade to the latest version of your
Django-related dependencies as well. If the Django version was recently
released or if some of your dependencies are not well-maintained, some of your
dependencies may not yet support the new Django version. In these cases you may
have to wait until new versions of your dependencies are released.
Resolving deprecation warnings
Before upgrading, it's a good idea to resolve any deprecation warnings raised
by your project while using your current version of Django. Fixing these
warnings before upgrading ensures that you're informed about areas of the code
that need altering.
In Python, deprecation warnings are silenced by default. You must turn them on
using the -Wall Python command line option or the :envvar:PYTHONWARNINGS
environment variable. For example, to show warnings while running tests:
.. code-block:: console
$ python -Wall manage.py testIf you're not using the Django test runner, you may need to also ensure that
any console output is not captured which would hide deprecation warnings. For
example, if you use py.test:
.. code-block:: console
$ PYTHONWARNINGS=all py.test tests --capture=noResolve any deprecation warnings with your current version of Django before
continuing the upgrade process.
Third party applications might use deprecated APIs in order to support multiple
versions of Django, so deprecation warnings in packages you've installed don't
necessarily indicate a problem. If a package doesn't support the latest version
of Django, consider raising an issue or sending a pull request for it.
Installation
Once you're ready, it is time to :doc:install the new Django version </topics/install>. If you are using virtualenv_ and it is a major upgrade, you
might want to set up a new environment with all the dependencies first.
Exactly which steps you will need to take depends on your installation process.
The most convenient way is to use pip_ with the --upgrade or -U flag:
.. code-block:: console
$ pip install -U Django
pip_ also automatically uninstalls the previous version of Django.
If you use some other installation process, you might have to manually
:ref:uninstall the old Django version <removing-old-versions-of-django> and
should look at the complete installation instructions.
.. _pip: https://pip.pypa.io/
.. _virtualenv: http://www.virtualenv.org/
Testing
When the new environment is set up, :doc:run the full test suite </topics/testing/overview> for your application. Again, it's useful to turn
on deprecation warnings on so they're shown in the test output (you can also
use the flag if you test your app manually using manage.py runserver):
.. code-block:: console
$ python -Wall manage.py testAfter you have run the tests, fix any failures. While you have the release
notes fresh in your mind, it may also be a good time to take advantage of new
features in Django by refactoring your code to eliminate any deprecation
warnings.
Deployment
When you are sufficiently confident your app works with the new version of
Django, you're ready to go ahead and :doc:deploy </howto/deployment/index>
your upgraded Django project.
If you are using caching provided by Django, you should consider clearing your
cache after upgrading. Otherwise you may run into problems, for example, if you
are caching pickled objects as these objects are not guaranteed to be
pickle-compatible across Django versions. A past instance of incompatibility
was caching pickled :class:~django.http.HttpResponse objects, either
directly or indirectly via the :func:~django.views.decorators.cache.cache_page
decorator.
大一小学期 Week 3 Python Exam 2016 Docs Howto Windows (`大一小学期/Week_3-Python/exam/2016/docs/howto/windows.txt`)
================================ How to install Django on Windows
This document will guide you through installing Python 3.5 and Django on
Windows. It also provides instructions for installing virtualenv_ andvirtualenvwrapper_, which make it easier to work on Python projects. This is
meant as a beginner's guide for users working on Django projects and does not
reflect how Django should be installed when developing patches for Django
itself.
The steps in this guide have been tested with Windows 7, 8, and 10. In other
versions, the steps would be similar. You will need to be familiar with using
the Windows command prompt.
Install Python
Django is a Python web framework, thus requiring Python to be installed on your
machine. At the time of writing, Python 3.5 is the latest version.
To install Python on your machine go to https://python.org/downloads/. The
website should offer you a download button for the latest Python version.
Download the executable installer and run it. Check the box next to Add Python 3.5 to PATH and then click Install Now.
After installation, open the command prompt and check that the Python version
matches the version you installed by executing::
python --versionAbout ``pip``
pip_ is a package manage for Python. It makes installing and uninstalling
Python packages (such as Django!) very easy. For the rest of the installation,
we'll use pip to install Python packages from the command line.
To install pip on your machine, go to
https://pip.pypa.io/en/latest/installing/, and follow the Installing with get-pip.py instructions.
.. _pip: https://pypi.python.org/pypi/pip
Install ``virtualenv`` and ``virtualenvwrapper``
virtualenv_ and virtualenvwrapper_ provide a dedicated environment for
each Django project you create. While not mandatory, this is considered a best
practice and will save you time in the future when you're ready to deploy your
project. Simply type::
pip install virtualenvwrapper-winThen create a virtual environment for your project::
mkvirtualenv myprojectThe virtual environment will be activated automatically and you'll see
"(myproject)" next to the command prompt to designate that. If you start a new
command prompt, you'll need to activate the environment again using::
workon myproject.. _virtualenv: https://pypi.python.org/pypi/virtualenv
.. _virtualenvwrapper: https://pypi.python.org/pypi/virtualenvwrapper-win
Install Django
Django can be installed easily using pip within your virtual environment.
In the command prompt, ensure your virtual environment is active, and execute
the following command::
pip install djangoThis will download and install the latest Django release.
After the installation has completed, you can verify your Django installation
by executing django-admin --version in the command prompt.
See :ref:database-installation for information on database installation
with Django.
Common pitfalls
If
django-adminonly displays the help text no matter what arguments
it is given, there is probably a problem with the file association in
Windows. Check if there is more than one environment variable set for
running Python scripts inPATH. This usually occurs when there is more
than one Python version installed.If you are connecting to the internet behind a proxy, there might be problem
in running the commandpip install django. Set the environment variables
for proxy configuration in the command prompt as follows::set http_proxy=http://username:password@proxyserver:proxyport
set https_proxy=https://username:password@proxyserver:proxyport
大一小学期 Week 3 Python Exam 2016 Docs Howto Writing Migrations (`大一小学期/Week_3-Python/exam/2016/docs/howto/writing-migrations.txt`)
=========================== Writing database migrations
This document explains how to structure and write database migrations for
different scenarios you might encounter. For introductory material on
migrations, see :doc:the topic guide </topics/migrations>.
.. _data-migrations-and-multiple-databases:
Data migrations and multiple databases
When using multiple databases, you may need to figure out whether or not to
run a migration against a particular database. For example, you may want to
only run a migration on a particular database.
In order to do that you can check the database connection's alias inside aRunPython operation by looking at the schema_editor.connection.alias
attribute::
from django.db import migrations
def forwards(apps, schema_editor):
if not schema_editor.connection.alias == 'default':
return
# Your migration code goes here
class Migration(migrations.Migration):
dependencies = [
# Dependencies to other migrations
]
operations = [
migrations.RunPython(forwards),
]You can also provide hints that will be passed to the :meth:allow_migrate()
method of database routers as **hints:
.. snippet::
:filename: myapp/dbrouters.py
class MyRouter(object):
def allow_migrate(self, db, app_label, model_name=None, **hints):
if 'target_db' in hints:
return db == hints['target_db']
return TrueThen, to leverage this in your migrations, do the following::
from django.db import migrations
def forwards(apps, schema_editor):
# Your migration code goes here
...
class Migration(migrations.Migration):
dependencies = [
# Dependencies to other migrations
]
operations = [
migrations.RunPython(forwards, hints={'target_db': 'default'}),
]If your RunPython or RunSQL operation only affects one model, it's good
practice to pass model_name as a hint to make it as transparent as possible
to the router. This is especially important for reusable and third-party apps.
Migrations that add unique fields
Applying a "plain" migration that adds a unique non-nullable field to a table
with existing rows will raise an error because the value used to populate
existing rows is generated only once, thus breaking the unique constraint.
Therefore, the following steps should be taken. In this example, we'll add a
non-nullable :class:~django.db.models.UUIDField with a default value. Modify
the respective field according to your needs.
Add the field on your model with
default=uuid.uuid4andunique=True
arguments (choose an appropriate default for the type of the field you're
adding).Run the :djadmin:
makemigrationscommand. This should generate a migration
with anAddFieldoperation.Generate two empty migration files for the same app by running
makemigrations myapp --emptytwice. We've renamed the migration files to
give them meaningful names in the examples below.Copy the
AddFieldoperation from the auto-generated migration (the first
of the three new files) to the last migration and changeAddFieldtoAlterField. For example:.. snippet::
:filename: 0006_remove_uuid_null.py-*- coding: utf-8 -*-
Generated by Django A.B on YYYY-MM-DD HH:MM
from future import unicode_literals
from django.db import migrations, models
import uuidclass Migration(migrations.Migration):
textdependencies = [ ('myapp', '0005_populate_uuid_values'), ] operations = [ migrations.AlterField( model_name='mymodel', name='uuid', field=models.UUIDField(default=uuid.uuid4, unique=True), ), ]Edit the first migration file. The generated migration class should look
similar to this:.. snippet::
:filename: 0004_add_uuid_field.pyclass Migration(migrations.Migration):
textdependencies = [ ('myapp', '0003_auto_20150129_1705'), ] operations = [ migrations.AddField( model_name='mymodel', name='uuid', field=models.UUIDField(default=uuid.uuid4, unique=True), ), ]Change
unique=Truetonull=True-- this will create the intermediary
null field and defer creating the unique constraint until we've populated
unique values on all the rows.In the first empty migration file, add a
:class:~django.db.migrations.operations.RunPythonor
:class:~django.db.migrations.operations.RunSQLoperation to generate a
unique value (UUID in the example) for each existing row. For example:.. snippet::
:filename: 0005_populate_uuid_values.py-*- coding: utf-8 -*-
Generated by Django A.B on YYYY-MM-DD HH:MM
from future import unicode_literals
from django.db import migrations, models
import uuiddef gen_uuid(apps, schema_editor):
MyModel = apps.get_model('myapp', 'MyModel')
for row in MyModel.objects.all():
row.uuid = uuid.uuid4()
row.save()class Migration(migrations.Migration):
textdependencies = [ ('myapp', '0004_add_uuid_field'), ] operations = [ # omit reverse_code=... if you don't want the migration to be reversible. migrations.RunPython(gen_uuid, reverse_code=migrations.RunPython.noop), ]Now you can apply the migrations as usual with the :djadmin:
migratecommand.Note there is a race condition if you allow objects to be created while this
migration is running. Objects created after theAddFieldand beforeRunPythonwill have their originaluuid’s overwritten.
.. _non-atomic-migrations:
Non-atomic migrations
.. versionadded:: 1.10
On databases that support DDL transactions (SQLite and PostgreSQL), migrations
will run inside a transaction by default. For use cases such as performing data
migrations on large tables, you may want to prevent a migration from running in
a transaction by setting the ``atomic`` attribute to ``False``::
from django.db import migrations
class Migration(migrations.Migration):
atomic = False
Within such a migration, all operations are run without a transaction. It's
possible to execute parts of the migration inside a transaction using
:func:`~django.db.transaction.atomic()` or by passing ``atomic=True`` to
``RunPython``.
Here's an example of a non-atomic data migration that updates a large table in
smaller batches::
import uuid
from django.db import migrations, transaction
def gen_uuid(apps, schema_editor):
MyModel = apps.get_model('myapp', 'MyModel')
while MyModel.objects.filter(uuid__isnull=True).exists():
with transaction.atomic():
for row in MyModel.objects.filter(uuid__isnull=True)[:1000]:
row.uuid = uuid.uuid4()
row.save()
class Migration(migrations.Migration):
atomic = False
operations = [
migrations.RunPython(gen_uuid),
]
The ``atomic`` attribute doesn't have an effect on databases that don't support
DDL transactions (e.g. MySQL, Oracle).
Controlling the order of migrations
===================================
Django determines the order in which migrations should be applied not by the
filename of each migration, but by building a graph using two properties on the
``Migration`` class: ``dependencies`` and ``run_before``.
If you've used the :djadmin:`makemigrations` command you've probably
already seen ``dependencies`` in action because auto-created
migrations have this defined as part of their creation process.
The ``dependencies`` property is declared like this::
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('myapp', '0123_the_previous_migration'),
]
Usually this will be enough, but from time to time you may need to
ensure that your migration runs *before* other migrations. This is
useful, for example, to make third-party apps' migrations run *after*
your :setting:`AUTH_USER_MODEL` replacement.
To achieve this, place all migrations that should depend on yours in
the ``run_before`` attribute on your ``Migration`` class::
class Migration(migrations.Migration):
...
run_before = [
('third_party_app', '0001_do_awesome'),
]
Prefer using ``dependencies`` over ``run_before`` when possible. You should
only use ``run_before`` if it is undesirable or impractical to specify
``dependencies`` in the migration which you want to run after the one you are
writing.
Migrating data between third-party apps
=======================================
You can use a data migration to move data from one third-party application to
another.
If you plan to remove the old app later, you'll need to set the ``dependencies``
property based on whether or not the old app is installed. Otherwise, you'll
have missing dependencies once you uninstall the old app. Similarly, you'll
need to catch :exc:`LookupError` in the ``apps.get_model()`` call that
retrieves models from the old app. This approach allows you to deploy your
project anywhere without first installing and then uninstalling the old app.
Here's a sample migration:
.. snippet::
:filename: myapp/migrations/0124_move_old_app_to_new_app.py
from django.apps import apps as global_apps
from django.db import migrations
def forwards(apps, schema_editor):
try:
OldModel = apps.get_model('old_app', 'OldModel')
except LookupError:
# The old app isn't installed.
return
NewModel = apps.get_model('new_app', 'NewModel')
NewModel.objects.bulk_create(
NewModel(new_attribute=old_object.old_attribute)
for old_object in OldModel.objects.all()
)
class Migration(migrations.Migration):
operations = [
migrations.RunPython(forwards, migrations.RunPython.noop),
]
dependencies = [
('myapp', '0123_the_previous_migration'),
('new_app', '0001_initial'),
]
if global_apps.is_installed('old_app'):
dependencies.append(('old_app', '0001_initial'))
Also consider what you want to happen when the migration is unapplied. You
could either do nothing (as in the example above) or remove some or all of the
data from the new application. Adjust the second argument of the
:mod:`~django.db.migrations.operations.RunPython` operation accordingly.
Changing an unmanaged model to managed
======================================
If you want to change an unmanaged model (:attr:`managed=False
<django.db.models.Options.managed>`) to managed, you must remove
``managed=False`` and generate a migration before making other schema-related
changes to the model, since schema changes that appear in the migration that
contains the operation to change ``Meta.managed`` may not be applied.
---
### 大一小学期 Week 3 Python Exam 2016 Docs Internals Deprecation (`大一小学期/Week_3-Python/exam/2016/docs/internals/deprecation.txt`)
===========================
Django Deprecation Timeline
===========================
This document outlines when various pieces of Django will be removed or altered
in a backward incompatible way, following their deprecation, as per the
:ref:`deprecation policy `. More details
about each item can often be found in the release notes of two versions prior.
.. _deprecation-removed-in-2.0:
2.0
---
See the :ref:`Django 1.9 release notes<deprecated-features-1.9>` for more
details on these changes.
* The ``weak`` argument to ``django.dispatch.signals.Signal.disconnect()`` will
be removed.
* The ``django.forms.extras`` package will be removed.
* The ``assignment_tag`` helper will be removed.
* The ``host`` argument to ``assertsRedirects`` will be removed. The
compatibility layer which allows absolute URLs to be considered equal to
relative ones when the path is identical will also be removed.
* ``Field.rel`` will be removed.
* ``Field.remote_field.to`` attribute will be removed.
* The ``on_delete`` argument for ``ForeignKey`` and ``OneToOneField`` will be
required.
* ``django.db.models.fields.add_lazy_relation()`` will be removed.
* When time zone support is enabled, database backends that don't support time
zones won't convert aware datetimes to naive values in UTC anymore when such
values are passed as parameters to SQL queries executed outside of the ORM,
e.g. with ``cursor.execute()``.
* The ``django.contrib.auth.tests.utils.skipIfCustomUser()`` decorator will be
removed.
* The ``GeoManager`` and ``GeoQuerySet`` classes will be removed.
* The ``django.contrib.gis.geoip`` module will be removed.
* The ``supports_recursion`` check for template loaders will be removed from:
* ``django.template.engine.Engine.find_template()``
* ``django.template.loader_tags.ExtendsNode.find_template()``
* ``django.template.loaders.base.Loader.supports_recursion()``
* ``django.template.loaders.cached.Loader.supports_recursion()``
* The ``load_template()`` and ``load_template_sources()`` template loader
methods will be removed.
* The ``template_dirs`` argument for template loaders will be removed:
* ``django.template.loaders.base.Loader.get_template()``
* ``django.template.loaders.cached.Loader.cache_key()``
* ``django.template.loaders.cached.Loader.get_template()``
* ``django.template.loaders.cached.Loader.get_template_sources()``
* ``django.template.loaders.filesystem.Loader.get_template_sources()``
* The ``django.template.loaders.base.Loader.__call__()`` method will be
removed.
* Support for custom error views with a single positional parameter will be
dropped.
* The ``mime_type`` attribute of ``django.utils.feedgenerator.Atom1Feed`` and
``django.utils.feedgenerator.RssFeed`` will be removed in favor of
``content_type``.
* The ``app_name`` argument to :func:`~django.conf.urls.include()` will be
removed.
* Support for passing a 3-tuple as the first argument to ``include()`` will
be removed.
* Support for setting a URL instance namespace without an application
namespace will be removed.
* ``Field._get_val_from_obj()`` will be removed in favor of
``Field.value_from_object()``.
* ``django.template.loaders.eggs.Loader`` will be removed.
* The ``current_app`` parameter to the ``contrib.auth`` views will be removed.
* The ``callable_obj`` keyword argument to
``SimpleTestCase.assertRaisesMessage()`` will be removed.
* Support for the ``allow_tags`` attribute on ``ModelAdmin`` methods will be
removed.
* The ``enclosure`` keyword argument to ``SyndicationFeed.add_item()`` will be
removed.
* The ``django.template.loader.LoaderOrigin`` and
``django.template.base.StringOrigin`` aliases for
``django.template.base.Origin`` will be removed.
See the :ref:`Django 1.10 release notes <deprecated-features-1.10>` for more
details on these changes.
* The ``makemigrations --exit`` option will be removed.
* Support for direct assignment to a reverse foreign key or many-to-many
relation will be removed.
* The ``get_srid()`` and ``set_srid()`` methods of
``django.contrib.gis.geos.GEOSGeometry`` will be removed.
* The ``get_x()``, ``set_x()``, ``get_y()``, ``set_y()``, ``get_z()``, and
``set_z()`` methods of ``django.contrib.gis.geos.Point`` will be removed.
* The ``get_coords()`` and ``set_coords()`` methods of
``django.contrib.gis.geos.Point`` will be removed.
* The ``cascaded_union`` property of ``django.contrib.gis.geos.MultiPolygon``
will be removed.
* ``django.utils.functional.allow_lazy()`` will be removed.
* The ``shell --plain`` option will be removed.
* The ``django.core.urlresolvers`` module will be removed.
* The model ``CommaSeparatedIntegerField`` will be removed. A stub field will
remain for compatibility with historical migrations.
* Support for the template ``Context.has_key()`` method will be removed.
* Support for the ``django.core.files.storage.Storage.accessed_time()``,
``created_time()``, and ``modified_time()`` methods will be removed.
* Support for query lookups using the model name when
``Meta.default_related_name`` is set will be removed.
* The ``__search`` query lookup and the
``DatabaseOperations.fulltext_search_sql()`` method will be removed.
* The shim for supporting custom related manager classes without a
``_apply_rel_filters()`` method will be removed.
* Using ``User.is_authenticated()`` and ``User.is_anonymous()`` as methods
will no longer be supported.
* The private attribute ``virtual_fields`` of ``Model._meta`` will be removed.
* The private keyword arguments ``virtual_only`` in
``Field.contribute_to_class()`` and ``virtual`` in
``Model._meta.add_field()`` will be removed.
* The ``javascript_catalog()`` and ``json_catalog()`` views will be removed.
* The ``django.contrib.gis.utils.precision_wkt()`` function will be removed.
* In multi-table inheritance, implicit promotion of a ``OneToOneField`` to a
``parent_link`` will be removed.
* Support for ``Widget._format_value()`` will be removed.
* ``FileField`` methods ``get_directory_name()`` and ``get_filename()`` will be
removed.
* The ``mark_for_escaping()`` function and the classes it uses: ``EscapeData``,
``EscapeBytes``, ``EscapeText``, ``EscapeString``, and ``EscapeUnicode`` will
be removed.
* The ``escape`` filter will change to use
``django.utils.html.conditional_escape()``.
* ``Manager.use_for_related_fields`` will be removed.
* Model ``Manager`` inheritance will follow MRO inheritance rules and the
``Meta.manager_inheritance_from_future`` to opt-in to this behavior will be
removed.
* Support for old-style middleware using ``settings.MIDDLEWARE_CLASSES`` will
be removed.
.. _deprecation-removed-in-1.10:
1.10
----
See the :ref:`Django 1.8 release notes<deprecated-features-1.8>` for more
details on these changes.
* Support for calling a ``SQLCompiler`` directly as an alias for calling its
``quote_name_unless_alias`` method will be removed.
* ``cycle`` and ``firstof`` template tags will be removed from the ``future``
template tag library (used during the 1.6/1.7 deprecation period).
* ``django.conf.urls.patterns()`` will be removed.
* Support for the ``prefix`` argument to
``django.conf.urls.i18n.i18n_patterns()`` will be removed.
* ``SimpleTestCase.urls`` will be removed.
* Using an incorrect count of unpacked values in the ``for`` template tag
will raise an exception rather than fail silently.
* The ability to reverse URLs using a dotted Python path will be removed.
* The ability to use a dotted Python path for the ``LOGIN_URL`` and
``LOGIN_REDIRECT_URL`` settings will be removed.
* Support for :py:mod:`optparse` will be dropped for custom management commands
(replaced by :py:mod:`argparse`).
* The class ``django.core.management.NoArgsCommand`` will be removed. Use
:class:`~django.core.management.BaseCommand` instead, which takes no arguments
by default.
* ``django.core.context_processors`` module will be removed.
* ``django.db.models.sql.aggregates`` module will be removed.
* ``django.contrib.gis.db.models.sql.aggregates`` module will be removed.
* The following methods and properties of ``django.db.sql.query.Query`` will
be removed:
* Properties: ``aggregates`` and ``aggregate_select``
* Methods: ``add_aggregate``, ``set_aggregate_mask``, and
``append_aggregate_mask``.
* ``django.template.resolve_variable`` will be removed.
* The following private APIs will be removed from
:class:`django.db.models.options.Options` (``Model._meta``):
* ``get_field_by_name()``
* ``get_all_field_names()``
* ``get_fields_with_model()``
* ``get_concrete_fields_with_model()``
* ``get_m2m_with_model()``
* ``get_all_related_objects()``
* ``get_all_related_objects_with_model()``
* ``get_all_related_many_to_many_objects()``
* ``get_all_related_m2m_objects_with_model()``
* The ``error_message`` argument of ``django.forms.RegexField`` will be removed.
* The ``unordered_list`` filter will no longer support old style lists.
* Support for string ``view`` arguments to ``url()`` will be removed.
* The backward compatible shim to rename ``django.forms.Form._has_changed()``
to ``has_changed()`` will be removed.
* The ``removetags`` template filter will be removed.
* The ``remove_tags()`` and ``strip_entities()`` functions in
``django.utils.html`` will be removed.
* The ``is_admin_site`` argument to
``django.contrib.auth.views.password_reset()`` will be removed.
* ``django.db.models.field.subclassing.SubfieldBase`` will be removed.
* ``django.utils.checksums`` will be removed; its functionality is included
in django-localflavor 1.1+.
* The ``original_content_type_id`` attribute on
``django.contrib.admin.helpers.InlineAdminForm`` will be removed.
* The backwards compatibility shim to allow ``FormMixin.get_form()`` to be
defined with no default value for its ``form_class`` argument will be removed.
* The following settings will be removed:
* ``ALLOWED_INCLUDE_ROOTS``
* ``TEMPLATE_CONTEXT_PROCESSORS``
* ``TEMPLATE_DEBUG``
* ``TEMPLATE_DIRS``
* ``TEMPLATE_LOADERS``
* ``TEMPLATE_STRING_IF_INVALID``
* The backwards compatibility alias ``django.template.loader.BaseLoader`` will
be removed.
* Django template objects returned by
:func:`~django.template.loader.get_template` and
:func:`~django.template.loader.select_template` won't accept a
:class:`~django.template.Context` in their
:meth:`~django.template.backends.base.Template.render()` method anymore.
* :doc:`Template response APIs </ref/template-response>` will enforce the use
of :class:`dict` and backend-dependent template objects instead of
:class:`~django.template.Context` and :class:`~django.template.Template`
respectively.
* The ``current_app`` parameter for the following function and classes will be
removed:
* ``django.shortcuts.render()``
* ``django.template.Context()``
* ``django.template.RequestContext()``
* ``django.template.response.TemplateResponse()``
* The ``dictionary`` and ``context_instance`` parameters for the following
functions will be removed:
* ``django.shortcuts.render()``
* ``django.shortcuts.render_to_response()``
* ``django.template.loader.render_to_string()``
* The ``dirs`` parameter for the following functions will be removed:
* ``django.template.loader.get_template()``
* ``django.template.loader.select_template()``
* ``django.shortcuts.render()``
* ``django.shortcuts.render_to_response()``
* Session verification will be enabled regardless of whether or not
``'django.contrib.auth.middleware.SessionAuthenticationMiddleware'`` is in
``MIDDLEWARE_CLASSES``.
* Private attribute ``django.db.models.Field.related`` will be removed.
* The ``--list`` option of the ``migrate`` management command will be removed.
* The ``ssi`` template tag will be removed.
* Support for the ``=`` comparison operator in the ``if`` template tag will be
removed.
* The backwards compatibility shims to allow ``Storage.get_available_name()``
and ``Storage.save()`` to be defined without a ``max_length`` argument will
be removed.
* Support for the legacy ``%(<foo>)s`` syntax in ``ModelFormMixin.success_url``
will be removed.
* ``GeoQuerySet`` aggregate methods ``collect()``, ``extent()``, ``extent3d()``,
``make_line()``, and ``unionagg()`` will be removed.
* Ability to specify ``ContentType.name`` when creating a content type instance
will be removed.
* Support for the old signature of ``allow_migrate`` will be removed. It changed
from ``allow_migrate(self, db, model)`` to
``allow_migrate(self, db, app_label, model_name=None, **hints)``.
* Support for the syntax of ``{% cycle %}`` that uses comma-separated arguments
will be removed.
* The warning that :class:`~django.core.signing.Signer` issues when given an
invalid separator will become an exception.
.. _deprecation-removed-in-1.9:
1.9
---
See the :ref:`Django 1.7 release notes<deprecated-features-1.7>` for more
details on these changes.
* ``django.utils.dictconfig`` will be removed.
* ``django.utils.importlib`` will be removed.
* ``django.utils.tzinfo`` will be removed.
* ``django.utils.unittest`` will be removed.
* The ``syncdb`` command will be removed.
* ``django.db.models.signals.pre_syncdb`` and
``django.db.models.signals.post_syncdb`` will be removed.
* ``allow_syncdb`` on database routers will no longer automatically become
``allow_migrate``.
* Automatic syncing of apps without migrations will be removed. Migrations will
become compulsory for all apps unless you pass the ``--run-syncdb`` option to
``migrate``.
* The SQL management commands for apps without migrations, ``sql``, ``sqlall``,
``sqlclear``, ``sqldropindexes``, and ``sqlindexes``, will be removed.
* Support for automatic loading of ``initial_data`` fixtures and initial SQL
data will be removed.
* All models will need to be defined inside an installed application or
declare an explicit :attr:`~django.db.models.Options.app_label`.
Furthermore, it won't be possible to import them before their application
is loaded. In particular, it won't be possible to import models inside
the root package of their application.
* The model and form ``IPAddressField`` will be removed. A stub field will
remain for compatibility with historical migrations.
* ``AppCommand.handle_app()`` will no longer be supported.
* ``RequestSite`` and ``get_current_site()`` will no longer be importable from
``django.contrib.sites.models``.
* FastCGI support via the ``runfcgi`` management command will be
removed. Please deploy your project using WSGI.
* ``django.utils.datastructures.SortedDict`` will be removed. Use
:class:`collections.OrderedDict` from the Python standard library instead.
* ``ModelAdmin.declared_fieldsets`` will be removed.
* Instances of ``util.py`` in the Django codebase have been renamed to
``utils.py`` in an effort to unify all util and utils references.
The modules that provided backwards compatibility will be removed:
* ``django.contrib.admin.util``
* ``django.contrib.gis.db.backends.util``
* ``django.db.backends.util``
* ``django.forms.util``
* ``ModelAdmin.get_formsets`` will be removed.
* The backward compatibility shim introduced to rename the
``BaseMemcachedCache._get_memcache_timeout()`` method to
``get_backend_timeout()`` will be removed.
* The ``--natural`` and ``-n`` options for :djadmin:`dumpdata` will be removed.
* The ``use_natural_keys`` argument for ``serializers.serialize()`` will be
removed.
* Private API ``django.forms.forms.get_declared_fields()`` will be removed.
* The ability to use a ``SplitDateTimeWidget`` with ``DateTimeField`` will be
removed.
* The ``WSGIRequest.REQUEST`` property will be removed.
* The class ``django.utils.datastructures.MergeDict`` will be removed.
* The ``zh-cn`` and ``zh-tw`` language codes will be removed and have been
replaced by the ``zh-hans`` and ``zh-hant`` language code respectively.
* The internal ``django.utils.functional.memoize`` will be removed.
* ``django.core.cache.get_cache`` will be removed. Add suitable entries
to :setting:`CACHES` and use :data:`django.core.cache.caches` instead.
* ``django.db.models.loading`` will be removed.
* Passing callable arguments to querysets will no longer be possible.
* ``BaseCommand.requires_model_validation`` will be removed in favor of
``requires_system_checks``. Admin validators will be replaced by admin
checks.
* The ``ModelAdmin.validator_class`` and ``default_validator_class`` attributes
will be removed.
* ``ModelAdmin.validate()`` will be removed.
* ``django.db.backends.DatabaseValidation.validate_field`` will be removed in
favor of the ``check_field`` method.
* The ``validate`` management command will be removed.
* ``django.utils.module_loading.import_by_path`` will be removed in favor of
``django.utils.module_loading.import_string``.
* ``ssi`` and ``url`` template tags will be removed from the ``future`` template
tag library (used during the 1.3/1.4 deprecation period).
* ``django.utils.text.javascript_quote`` will be removed.
* Database test settings as independent entries in the database settings,
prefixed by ``TEST_``, will no longer be supported.
* The `cache_choices` option to :class:`~django.forms.ModelChoiceField` and
:class:`~django.forms.ModelMultipleChoiceField` will be removed.
* The default value of the
:attr:`RedirectView.permanent <django.views.generic.base.RedirectView.permanent>`
attribute will change from ``True`` to ``False``.
* ``django.contrib.sitemaps.FlatPageSitemap`` will be removed in favor of
``django.contrib.flatpages.sitemaps.FlatPageSitemap``.
* Private API ``django.test.utils.TestTemplateLoader`` will be removed.
* The ``django.contrib.contenttypes.generic`` module will be removed.
* Private APIs ``django.db.models.sql.where.WhereNode.make_atom()`` and
``django.db.models.sql.where.Constraint`` will be removed.
.. _deprecation-removed-in-1.8:
1.8
---
See the :ref:`Django 1.6 release notes<deprecated-features-1.6>` for more
details on these changes.
* ``django.contrib.comments`` will be removed.
* The following transaction management APIs will be removed:
- ``TransactionMiddleware``,
- the decorators and context managers ``autocommit``, ``commit_on_success``,
and ``commit_manually``, defined in ``django.db.transaction``,
- the functions ``commit_unless_managed`` and ``rollback_unless_managed``,
also defined in ``django.db.transaction``,
- the ``TRANSACTIONS_MANAGED`` setting.
* The :ttag:`cycle` and :ttag:`firstof` template tags will auto-escape their
arguments. In 1.6 and 1.7, this behavior is provided by the version of these
tags in the ``future`` template tag library.
* The ``SEND_BROKEN_LINK_EMAILS`` setting will be removed. Add the
:class:`django.middleware.common.BrokenLinkEmailsMiddleware` middleware to
your :setting:`MIDDLEWARE_CLASSES` setting instead.
* ``django.middleware.doc.XViewMiddleware`` will be removed. Use
``django.contrib.admindocs.middleware.XViewMiddleware`` instead.
* ``Model._meta.module_name`` was renamed to ``model_name``.
* Remove the backward compatible shims introduced to rename ``get_query_set``
and similar queryset methods. This affects the following classes:
``BaseModelAdmin``, ``ChangeList``, ``BaseCommentNode``,
``GenericForeignKey``, ``Manager``, ``SingleRelatedObjectDescriptor`` and
``ReverseSingleRelatedObjectDescriptor``.
* Remove the backward compatible shims introduced to rename the attributes
``ChangeList.root_query_set`` and ``ChangeList.query_set``.
* ``django.views.defaults.shortcut`` will be removed, as part of the
goal of removing all ``django.contrib`` references from the core
Django codebase. Instead use
``django.contrib.contenttypes.views.shortcut``. ``django.conf.urls.shortcut``
will also be removed.
* Support for the Python Imaging Library (PIL) module will be removed, as it
no longer appears to be actively maintained & does not work on Python 3.
You are advised to install `Pillow`_, which should be used instead.
.. _`Pillow`: https://pypi.python.org/pypi/Pillow
* The following private APIs will be removed:
- ``django.db.backend``
- ``django.db.close_connection()``
- ``django.db.backends.creation.BaseDatabaseCreation.set_autocommit()``
- ``django.db.transaction.is_managed()``
- ``django.db.transaction.managed()``
* ``django.forms.widgets.RadioInput`` will be removed in favor of
``django.forms.widgets.RadioChoiceInput``.
* The module ``django.test.simple`` and the class
``django.test.simple.DjangoTestSuiteRunner`` will be removed. Instead use
``django.test.runner.DiscoverRunner``.
* The module ``django.test._doctest`` will be removed. Instead use the doctest
module from the Python standard library.
* The ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting will be removed.
* Usage of the hard-coded *Hold down "Control", or "Command" on a Mac, to select
more than one.* string to override or append to user-provided ``help_text`` in
forms for ManyToMany model fields will not be performed by Django anymore
either at the model or forms layer.
* The ``Model._meta.get_(add|change|delete)_permission`` methods will
be removed.
* The session key ``django_language`` will no longer be read for backwards
compatibility.
* Geographic Sitemaps will be removed
(``django.contrib.gis.sitemaps.views.index`` and
``django.contrib.gis.sitemaps.views.sitemap``).
* ``django.utils.html.fix_ampersands``, the ``fix_ampersands`` template filter and
``django.utils.html.clean_html`` will be removed following an accelerated deprecation.
.. _deprecation-removed-in-1.7:
1.7
---
See the :ref:`Django 1.5 release notes<deprecated-features-1.5>` for more
details on these changes.
* The module ``django.utils.simplejson`` will be removed. The standard library
provides :mod:`json` which should be used instead.
* The function ``django.utils.itercompat.product`` will be removed. The Python
builtin version should be used instead.
* Auto-correction of INSTALLED_APPS and TEMPLATE_DIRS settings when they are
specified as a plain string instead of a tuple will be removed and raise an
exception.
* The ``mimetype`` argument to the ``__init__`` methods of
:class:`~django.http.HttpResponse`,
:class:`~django.template.response.SimpleTemplateResponse`, and
:class:`~django.template.response.TemplateResponse`, will be removed.
``content_type`` should be used instead. This also applies to the
``render_to_response()`` shortcut and the sitemap views,
:func:`~django.contrib.sitemaps.views.index` and
:func:`~django.contrib.sitemaps.views.sitemap`.
* When :class:`~django.http.HttpResponse` is instantiated with an iterator,
or when :attr:`~django.http.HttpResponse.content` is set to an iterator,
that iterator will be immediately consumed.
* The ``AUTH_PROFILE_MODULE`` setting, and the ``get_profile()`` method on
the User model, will be removed.
* The ``cleanup`` management command will be removed. It's replaced by
``clearsessions``.
* The ``daily_cleanup.py`` script will be removed.
* The ``depth`` keyword argument will be removed from
:meth:`~django.db.models.query.QuerySet.select_related`.
* The undocumented ``get_warnings_state()``/``restore_warnings_state()``
functions from :mod:`django.test.utils` and the ``save_warnings_state()``/
``restore_warnings_state()``
:ref:`django.test.*TestCase <django-testcase-subclasses>` methods are
deprecated. Use the :class:`warnings.catch_warnings` context manager
available starting with Python 2.6 instead.
* The undocumented ``check_for_test_cookie`` method in
:class:`~django.contrib.auth.forms.AuthenticationForm` will be removed
following an accelerated deprecation. Users subclassing this form should
remove calls to this method, and instead ensure that their auth related views
are CSRF protected, which ensures that cookies are enabled.
* The version of :func:`django.contrib.auth.views.password_reset_confirm` that
supports base36 encoded user IDs
(``django.contrib.auth.views.password_reset_confirm_uidb36``) will be
removed. If your site has been running Django 1.6 for more than
:setting:`PASSWORD_RESET_TIMEOUT_DAYS`, this change will have no effect. If
not, then any password reset links generated before you upgrade to Django 1.7
won't work after the upgrade.
* The ``django.utils.encoding.StrAndUnicode`` mix-in will be removed.
Define a ``__str__`` method and apply the
:func:`~django.utils.encoding.python_2_unicode_compatible` decorator instead.
.. _deprecation-removed-in-1.6:
1.6
---
See the :ref:`Django 1.4 release notes<deprecated-features-1.4>` for more
details on these changes.
* ``django.contrib.databrowse`` will be removed.
* ``django.contrib.localflavor`` will be removed following an accelerated
deprecation.
* ``django.contrib.markup`` will be removed following an accelerated
deprecation.
* The compatibility modules ``django.utils.copycompat`` and
``django.utils.hashcompat`` as well as the functions
``django.utils.itercompat.all`` and ``django.utils.itercompat.any`` will
be removed. The Python builtin versions should be used instead.
* The ``csrf_response_exempt`` and ``csrf_view_exempt`` decorators will
be removed. Since 1.4 ``csrf_response_exempt`` has been a no-op (it
returns the same function), and ``csrf_view_exempt`` has been a
synonym for ``django.views.decorators.csrf.csrf_exempt``, which should
be used to replace it.
* The ``django.core.cache.backends.memcached.CacheClass`` backend
was split into two in Django 1.3 in order to introduce support for
PyLibMC. The historical ``CacheClass`` will be removed in favor of
``django.core.cache.backends.memcached.MemcachedCache``.
* The UK-prefixed objects of ``django.contrib.localflavor.uk`` will only
be accessible through their GB-prefixed names (GB is the correct
ISO 3166 code for United Kingdom).
* The ``IGNORABLE_404_STARTS`` and ``IGNORABLE_404_ENDS`` settings have been
superseded by :setting:`IGNORABLE_404_URLS` in the 1.4 release. They will be
removed.
* The form wizard has been refactored to use class-based views with pluggable
backends in 1.4. The previous implementation will be removed.
* Legacy ways of calling
:func:`~django.views.decorators.cache.cache_page` will be removed.
* The backward-compatibility shim to automatically add a debug-false
filter to the ``'mail_admins'`` logging handler will be removed. The
:setting:`LOGGING` setting should include this filter explicitly if
it is desired.
* The builtin truncation functions ``django.utils.text.truncate_words()``
and ``django.utils.text.truncate_html_words()`` will be removed in
favor of the ``django.utils.text.Truncator`` class.
* The :class:`~django.contrib.gis.geoip.GeoIP` class was moved to
:mod:`django.contrib.gis.geoip` in 1.4 -- the shortcut in
:mod:`django.contrib.gis.utils` will be removed.
* ``django.conf.urls.defaults`` will be removed. The functions
:func:`~django.conf.urls.include`, ``patterns()`` and
:func:`~django.conf.urls.url` plus :data:`~django.conf.urls.handler404`,
:data:`~django.conf.urls.handler500`, are now available through
:mod:`django.conf.urls` .
* The functions ``setup_environ()`` and ``execute_manager()`` will be removed
from :mod:`django.core.management`. This also means that the old (pre-1.4)
style of :file:`manage.py` file will no longer work.
* Setting the ``is_safe`` and ``needs_autoescape`` flags as attributes of
template filter functions will no longer be supported.
* The attribute ``HttpRequest.raw_post_data`` was renamed to ``HttpRequest.body``
in 1.4. The backward compatibility will be removed --
``HttpRequest.raw_post_data`` will no longer work.
* The value for the ``post_url_continue`` parameter in
``ModelAdmin.response_add()`` will have to be either ``None`` (to redirect
to the newly created object's edit page) or a pre-formatted url. String
formats, such as the previous default ``'../%s/'``, will not be accepted any
more.
.. _deprecation-removed-in-1.5:
1.5
---
See the :ref:`Django 1.3 release notes<deprecated-features-1.3>` for more
details on these changes.
* Starting Django without a :setting:`SECRET_KEY` will result in an exception
rather than a ``DeprecationWarning``. (This is accelerated from the usual
deprecation path; see the :doc:`Django 1.4 release notes</releases/1.4>`.)
* The ``mod_python`` request handler will be removed. The ``mod_wsgi``
handler should be used instead.
* The ``template`` attribute on ``django.test.client.Response``
objects returned by the :ref:`test client <test-client>` will be removed.
The :attr:`~django.test.Response.templates` attribute should be
used instead.
* The ``django.test.simple.DjangoTestRunner`` will be removed.
Instead use a unittest-native class. The features of the
``django.test.simple.DjangoTestRunner`` (including fail-fast and
Ctrl-C test termination) can currently be provided by the unittest-native
:class:`~unittest.TextTestRunner`.
* The undocumented function
``django.contrib.formtools.utils.security_hash`` will be removed,
instead use ``django.contrib.formtools.utils.form_hmac``
* The function-based generic view modules will be removed in favor of their
class-based equivalents, outlined :doc:`here
</topics/class-based-views/index>`.
* The ``django.core.servers.basehttp.AdminMediaHandler`` will be
removed. In its place use
``django.contrib.staticfiles.handlers.StaticFilesHandler``.
* The template tags library ``adminmedia`` and the template tag ``{%
admin_media_prefix %}`` will be removed in favor of the generic static files
handling. (This is faster than the usual deprecation path; see the
:doc:`Django 1.4 release notes</releases/1.4>`.)
* The ``url`` and ``ssi`` template tags will be modified so that the first
argument to each tag is a template variable, not an implied string. In 1.4,
this behavior is provided by a version of the tag in the ``future`` template
tag library.
* The ``reset`` and ``sqlreset`` management commands will be removed.
* Authentication backends will need to support an inactive user
being passed to all methods dealing with permissions.
The ``supports_inactive_user`` attribute will no longer be checked
and can be removed from custom backends.
* :meth:`~django.contrib.gis.geos.GEOSGeometry.transform` will raise
a :class:`~django.contrib.gis.geos.GEOSException` when called
on a geometry with no SRID value.
* ``django.http.CompatCookie`` will be removed in favor of
``django.http.SimpleCookie``.
* ``django.core.context_processors.PermWrapper`` and
``django.core.context_processors.PermLookupDict`` will be removed in
favor of the corresponding
``django.contrib.auth.context_processors.PermWrapper`` and
``django.contrib.auth.context_processors.PermLookupDict``, respectively.
* The :setting:`MEDIA_URL` or :setting:`STATIC_URL` settings will be
required to end with a trailing slash to ensure there is a consistent
way to combine paths in templates.
* ``django.db.models.fields.URLField.verify_exists`` will be removed. The
feature was deprecated in 1.3.1 due to intractable security and
performance issues and will follow a slightly accelerated deprecation
timeframe.
* Translations located under the so-called *project path* will be ignored during
the translation building process performed at runtime. The
:setting:`LOCALE_PATHS` setting can be used for the same task by including the
filesystem path to a ``locale`` directory containing non-app-specific
translations in its value.
* The Markup contrib app will no longer support versions of Python-Markdown
library earlier than 2.1. An accelerated timeline was used as this was
a security related deprecation.
* The ``CACHE_BACKEND`` setting will be removed. The cache backend(s) should be
specified in the :setting:`CACHES` setting.
.. _deprecation-removed-in-1.4:
1.4
---
See the :ref:`Django 1.2 release notes<deprecated-features-1.2>` for more
details on these changes.
* ``CsrfResponseMiddleware`` and ``CsrfMiddleware`` will be removed. Use
the ``{% csrf_token %}`` template tag inside forms to enable CSRF
protection. ``CsrfViewMiddleware`` remains and is enabled by default.
* The old imports for CSRF functionality (``django.contrib.csrf.*``),
which moved to core in 1.2, will be removed.
* The ``django.contrib.gis.db.backend`` module will be removed in favor
of the specific backends.
* ``SMTPConnection`` will be removed in favor of a generic Email backend API.
* The many to many SQL generation functions on the database backends
will be removed.
* The ability to use the ``DATABASE_*`` family of top-level settings to
define database connections will be removed.
* The ability to use shorthand notation to specify a database backend
(i.e., ``sqlite3`` instead of ``django.db.backends.sqlite3``) will be
removed.
* The ``get_db_prep_save``, ``get_db_prep_value`` and
``get_db_prep_lookup`` methods will have to support multiple databases.
* The ``Message`` model (in ``django.contrib.auth``), its related
manager in the ``User`` model (``user.message_set``), and the
associated methods (``user.message_set.create()`` and
``user.get_and_delete_messages()``), will be removed. The
:doc:`messages framework </ref/contrib/messages>` should be used
instead. The related ``messages`` variable returned by the
auth context processor will also be removed. Note that this
means that the admin application will depend on the messages
context processor.
* Authentication backends will need to support the ``obj`` parameter for
permission checking. The ``supports_object_permissions`` attribute
will no longer be checked and can be removed from custom backends.
* Authentication backends will need to support the ``AnonymousUser`` class
being passed to all methods dealing with permissions. The
``supports_anonymous_user`` variable will no longer be checked and can be
removed from custom backends.
* The ability to specify a callable template loader rather than a
``Loader`` class will be removed, as will the ``load_template_source``
functions that are included with the built in template loaders for
backwards compatibility.
* ``django.utils.translation.get_date_formats()`` and
``django.utils.translation.get_partial_date_formats()``. These functions
will be removed; use the locale-aware
``django.utils.formats.get_format()`` to get the appropriate formats.
* In ``django.forms.fields``, the constants: ``DEFAULT_DATE_INPUT_FORMATS``,
``DEFAULT_TIME_INPUT_FORMATS`` and
``DEFAULT_DATETIME_INPUT_FORMATS`` will be removed. Use
``django.utils.formats.get_format()`` to get the appropriate
formats.
* The ability to use a function-based test runner will be removed,
along with the ``django.test.simple.run_tests()`` test runner.
* The ``views.feed()`` view and ``feeds.Feed`` class in
``django.contrib.syndication`` will be removed. The class-based view
``views.Feed`` should be used instead.
* ``django.core.context_processors.auth``. This release will
remove the old method in favor of the new method in
``django.contrib.auth.context_processors.auth``.
* The ``postgresql`` database backend will be removed, use the
``postgresql_psycopg2`` backend instead.
* The ``no`` language code will be removed and has been replaced by the
``nb`` language code.
* Authentication backends will need to define the boolean attribute
``supports_inactive_user`` until version 1.5 when it will be assumed that
all backends will handle inactive users.
* ``django.db.models.fields.XMLField`` will be removed. This was
deprecated as part of the 1.3 release. An accelerated deprecation
schedule has been used because the field hasn't performed any role
beyond that of a simple ``TextField`` since the removal of ``oldforms``.
All uses of ``XMLField`` can be replaced with ``TextField``.
* The undocumented ``mixin`` parameter to the ``open()`` method of
``django.core.files.storage.Storage`` (and subclasses) will be removed.
.. _deprecation-removed-in-1.3:
1.3
---
See the :ref:`Django 1.1 release notes<deprecated-features-1.1>` for more
details on these changes.
* ``AdminSite.root()``. This method of hooking up the admin URLs will be
removed in favor of including ``admin.site.urls``.
* Authentication backends need to define the boolean attributes
``supports_object_permissions`` and ``supports_anonymous_user`` until
version 1.4, at which point it will be assumed that all backends will
support these options.
---
### 大一小学期 Week 3 Python Exam 2016 Docs Internals Git (`大一小学期/Week_3-Python/exam/2016/docs/internals/git.txt`)
=================================
The Django source code repository
=================================
When deploying a Django application into a real production environment, you
will almost always want to use `an official packaged release of Django`_.
However, if you'd like to try out in-development code from an upcoming release
or contribute to the development of Django, you'll need to obtain a clone of
Django's source code repository.
This document covers the way the code repository is laid out and how to work
with and find things in it.
.. _an official packaged release of Django: https://www.djangoproject.com/download/
High-level overview
===================
The Django source code repository uses `Git`_ to track changes to the code
over time, so you'll need a copy of the Git client (a program called ``git``)
on your computer, and you'll want to familiarize yourself with the basics of
how Git works.
Git's website offers downloads for various operating systems. The site also
contains vast amounts of `documentation`_.
The Django Git repository is located online at `github.com/django/django
<https://github.com/django/django>`_. It contains the full source code for all
Django releases, which you can browse online.
The Git repository includes several `branches`_:
* ``master`` contains the main in-development code which will become
the next packaged release of Django. This is where most development
activity is focused.
* ``stable/A.B.x`` are the branches where release preparation work happens.
They are also used for bugfix and security releases which occur as necessary
after the initial release of a feature version.
* ``soc20XX/`` branches were used by students who worked on Django
during the 2009 and 2010 Google Summer of Code programs.
* ``attic/`` branches were used to develop major or experimental new
features without affecting the rest of Django's code.
The Git repository also contains `tags`_. These are the exact revisions from
which packaged Django releases were produced, since version 1.0.
The source code for the `Djangoproject.com <https://www.djangoproject.com/>`_
website can be found at `github.com/django/djangoproject.com
<https://github.com/django/djangoproject.com>`_.
.. _Git: http://git-scm.com/
.. _documentation: http://git-scm.com/documentation
.. _branches: https://github.com/django/django/branches
.. _tags: https://github.com/django/django/tags
The master branch
=================
If you'd like to try out the in-development code for the next release of
Django, or if you'd like to contribute to Django by fixing bugs or developing
new features, you'll want to get the code from the master branch.
Note that this will get *all* of Django: in addition to the top-level
``django`` module containing Python code, you'll also get a copy of Django's
documentation, test suite, packaging scripts and other miscellaneous bits.
Django's code will be present in your clone as a directory named
``django``.
To try out the in-development code with your own applications, simply place
the directory containing your clone on your Python import path. Then
``import`` statements which look for Django will find the ``django`` module
within your clone.
If you're going to be working on Django's code (say, to fix a bug or
develop a new feature), you can probably stop reading here and move
over to :doc:`the documentation for contributing to Django
`, which covers things like the preferred
coding style and how to generate and submit a patch.
Other branches
==============
Django uses branches to prepare for releases of Django.
In the past when Django was hosted on Subversion, branches were also used for
feature development. Now Django is hosted on Git and feature development is
done on contributor's forks, but the Subversion feature branches remain in Git
for historical reference.
Stable branches
---------------
These branches can be found in the repository as ``stable/A.B.x``
branches and will be created right after the first alpha is tagged.
For example, immediately after *Django 1.5 alpha 1* was tagged, the branch
``stable/1.5.x`` was created and all further work on preparing the code for the
final 1.5 release was done there.
These branches also provide limited bugfix support for the most recent released
version of Django and security support for the two most recently-released
versions of Django.
For example, after the release of Django 1.5, the branch ``stable/1.5.x``
receives only fixes for security and critical stability bugs, which are
eventually released as Django 1.5.1 and so on, ``stable/1.4.x`` receives only
security fixes, and ``stable/1.3.x`` no longer receives any updates.
.. admonition:: Historical information
This policy for handling ``stable/A.B.x`` branches was adopted starting
with the Django 1.5 release cycle.
Previously, these branches weren't created until right after the releases
and the stabilization work occurred on the main repository branch. Thus,
no new features development work for the next release of Django could be
committed until the final release happened.
For example, shortly after the release of Django 1.3 the branch
``stable/1.3.x`` was created. Official support for that release has expired,
and so it no longer receives direct maintenance from the Django project.
However, that and all other similarly named branches continue to exist and
interested community members have occasionally used them to provide
unofficial support for old Django releases.
Feature-development branches
----------------------------
.. admonition:: Historical information
Since Django moved to Git in 2012, anyone can clone the repository and
create their own branches, alleviating the need for official branches in
the source code repository.
The following section is mostly useful if you're exploring the repository's
history, for example if you're trying to understand how some features were
designed.
Feature-development branches tend by their nature to be temporary. Some
produce successful features which are merged back into Django's master to
become part of an official release, but others do not; in either case there
comes a time when the branch is no longer being actively worked on by any
developer. At this point the branch is considered closed.
Unfortunately, Django used to be maintained with the Subversion revision
control system, that has no standard way of indicating this. As a workaround,
branches of Django which are closed and no longer maintained were moved into
``attic``.
For reference, the following are branches whose code eventually became
part of Django itself, and so are no longer separately maintained:
* ``boulder-oracle-sprint``: Added support for Oracle databases to
Django's object-relational mapper. This has been part of Django
since the 1.0 release.
* ``gis``: Added support for geographic/spatial queries to Django's
object-relational mapper. This has been part of Django since the 1.0
release, as the bundled application ``django.contrib.gis``.
* ``i18n``: Added :doc:`internationalization support </topics/i18n/index>` to
Django. This has been part of Django since the 0.90 release.
* ``magic-removal``: A major refactoring of both the internals and
public APIs of Django's object-relational mapper. This has been part
of Django since the 0.95 release.
* ``multi-auth``: A refactoring of :doc:`Django's bundled
authentication framework </topics/auth/index>` which added support for
:ref:`authentication backends <authentication-backends>`. This has
been part of Django since the 0.95 release.
* ``new-admin``: A refactoring of :doc:`Django's bundled
administrative application </ref/contrib/admin/index>`. This became part of
Django as of the 0.91 release, but was superseded by another
refactoring (see next listing) prior to the Django 1.0 release.
* ``newforms-admin``: The second refactoring of Django's bundled
administrative application. This became part of Django as of the 1.0
release, and is the basis of the current incarnation of
``django.contrib.admin``.
* ``queryset-refactor``: A refactoring of the internals of Django's
object-relational mapper. This became part of Django as of the 1.0
release.
* ``unicode``: A refactoring of Django's internals to consistently use
Unicode-based strings in most places within Django and Django
applications. This became part of Django as of the 1.0 release.
When Django moved from SVN to Git, the information about branch merges wasn't
preserved in the source code repository. This means that the ``master`` branch
of Django doesn't contain merge commits for the above branches.
However, this information is `available as a grafts file`_. You can restore it
by putting the following lines in ``.git/info/grafts`` in your local clone::
ac64e91a0cadc57f4bc5cd5d66955832320ca7a1 553a20075e6991e7a60baee51ea68c8adc520d9a 0cb8e31823b2e9f05c4ae868c19f5f38e78a5f2e
79e68c225b926302ebb29c808dda8afa49856f5c d0f57e7c7385a112cb9e19d314352fc5ed5b0747 aa239e3e5405933af6a29dac3cf587b59a099927
5cf8f684237ab5addaf3549b2347c3adf107c0a7 cb45fd0ae20597306cd1f877efc99d9bd7cbee98 e27211a0deae2f1d402537f0ebb64ad4ccf6a4da
f69cf70ed813a8cd7e1f963a14ae39103e8d5265 d5dbeaa9be359a4c794885c2e9f1b5a7e5e51fb8 d2fcbcf9d76d5bb8a661ee73dae976c74183098b
aab3a418ac9293bb4abd7670f65d930cb0426d58 4ea7a11659b8a0ab07b0d2e847975f7324664f10 adf4b9311d5d64a2bdd58da50271c121ea22e397
ff60c5f9de3e8690d1e86f3e9e3f7248a15397c8 7ef212af149540aa2da577a960d0d87029fd1514 45b4288bb66a3cda401b45901e85b645674c3988
9dda4abee1225db7a7b195b84c915fdd141a7260 4fe5c9b7ee09dc25921918a6dbb7605edb374bc9 3a7c14b583621272d4ef53061287b619ce3c290d
a19ed8aea395e8e07164ff7d85bd7dff2f24edca dc375fb0f3b7fbae740e8cfcd791b8bccb8a4e66 42ea7a5ce8aece67d16c6610a49560c1493d4653
9c52d56f6f8a9cdafb231adf9f4110473099c9b5 c91a30f00fd182faf8ca5c03cd7dbcf8b735b458 4a5c5c78f2ecd4ed8859cd5ac773ff3a01bccf96
953badbea5a04159adbfa970f5805c0232b6a401 4c958b15b250866b70ded7d82aa532f1e57f96ae 5664a678b29ab04cad425c15b2792f4519f43928
471596fc1afcb9c6258d317c619eaf5fd394e797 4e89105d64bb9e04c409139a41e9c7aac263df4c 3e9035a9625c8a8a5e88361133e87ce455c4fc13
9233d0426537615e06b78d28010d17d5a66adf44 6632739e94c6c38b4c5a86cf5c80c48ae50ac49f 18e151bc3f8a85f2766d64262902a9fcad44d937
.. _available as a grafts file: https://github.com/ramiro/django-git-grafts
Additionally, the following branches are closed, but their code was
never merged into Django and the features they aimed to implement
were never finished:
* ``full-history``
* ``generic-auth``
* ``multiple-db-support``
* ``per-object-permissions``
* ``schema-evolution``
* ``schema-evolution-ng``
* ``search-api``
* ``sqlalchemy``
All of the above-mentioned branches now reside in ``attic``.
Finally, the repository contains ``soc2009/xxx`` and ``soc2010/xxx`` feature
branches, used for Google Summer of Code projects.
Tags
====
Each Django release is tagged and signed by a :ref:`releaser
<releasers-list>`.
The tags can be found on GitHub's `tags`_ page.
.. _tags: https://github.com/django/django/tags
---
### 大一小学期 Week 3 Python Exam 2016 Docs Internals Howto Release Django (`大一小学期/Week_3-Python/exam/2016/docs/internals/howto-release-django.txt`)
=====================
How is Django Formed?
=====================
.. highlight:: console
This document explains how to release Django.
**Please, keep these instructions up-to-date if you make changes!** The point
here is to be descriptive, not prescriptive, so feel free to streamline or
otherwise make changes, but **update this document accordingly!**
Overview
========
There are three types of releases that you might need to make:
* Security releases: disclosing and fixing a vulnerability. This'll
generally involve two or three simultaneous releases -- e.g.
1.5.x, 1.6.x, and, depending on timing, perhaps a 1.7 alpha/beta/rc.
* Regular version releases: either a final release (e.g. 1.5) or a
bugfix update (e.g. 1.5.1).
* Pre-releases: e.g. 1.6 alpha, beta, or rc.
The short version of the steps involved is:
#. If this is a security release, pre-notify the security distribution list
one week before the actual release.
#. Proofread the release notes, looking for organization and writing errors.
Draft a blog post and email announcement.
#. Update version numbers and create the release package(s).
#. Upload the package(s) to the ``djangoproject.com`` server.
#. Upload the new version(s) to PyPI.
#. Declare the new version in the admin on ``djangoproject.com``.
#. Post the blog entry and send out the email announcements.
#. Update version numbers post-release.
There are a lot of details, so please read on.
Prerequisites
=============
You'll need a few things before getting started:
* A GPG key. If the key you want to use is not your default signing key, you'll
need to add ``-u [email protected]`` to every GPG signing command below, where
``[email protected]`` is the email address associated with the key you want to
use.
* An install of some required Python packages::
$ pip install wheel twine
* Access to Django's record on PyPI. Create a file with your credentials:
.. snippet::
:filename: ~/.pypirc
[pypi]
username:YourUsername
password:YourPassword
* Access to the ``djangoproject.com`` server to upload files.
* Access to the admin on ``djangoproject.com`` as a "Site maintainer".
* Access to post to ``django-announce``.
* If this is a security release, access to the pre-notification distribution
list.
If this is your first release, you'll need to coordinate with James and/or
Jacob to get all these things lined up.
Pre-release tasks
=================
A few items need to be taken care of before even beginning the release process.
This stuff starts about a week before the release; most of it can be done
any time leading up to the actual release:
#. If this is a security release, send out pre-notification **one week** before
the release. We maintain a list of who gets these pre-notification emails in
the private ``django-core`` repository. Send the mail to
``[email protected]`` and BCC the pre-notification recipients.
This email should be signed by the key you'll use for the release, and
should include patches for each issue being fixed.
#. As the release approaches, watch Trac to make sure no release blockers
are left for the upcoming release.
#. Check with the other committers to make sure they don't have any
uncommitted changes for the release.
#. Proofread the release notes, including looking at the online
version to catch any broken links or reST errors, and make sure the
release notes contain the correct date.
#. Double-check that the release notes mention deprecation timelines
for any APIs noted as deprecated, and that they mention any changes
in Python version support.
#. Double-check that the release notes index has a link to the notes
for the new release; this will be in ``docs/releases/index.txt``.
#. If this is a feature release, ensure translations from Transifex have been
integrated. This is typically done by a separate translation's manager
rather than the releaser, but here are the steps. Provided you have an
account on Transifex::
$ python scripts/manage_translations.py fetch
and then commit the changed/added files (both .po and .mo). Sometimes there
are validation errors which need to be debugged, so avoid doing this task
immediately before a release is needed.
#. :ref:`Update the django-admin manual page <django-admin-manpage>`::
$ cd docs
$ make man
$ man _build/man/django-admin.1 # do a quick sanity check
$ cp _build/man/django-admin.1 man/django-admin.1
and then commit the changed man page.
Preparing for release
=====================
Write the announcement blog post for the release. You can enter it into the
admin at any time and mark it as inactive. Here are a few examples: `example
security release announcement`__, `example regular release announcement`__,
`example pre-release announcement`__.
__ https://www.djangoproject.com/weblog/2013/feb/19/security/
__ https://www.djangoproject.com/weblog/2012/mar/23/14/
__ https://www.djangoproject.com/weblog/2012/nov/27/15-beta-1/
Actually rolling the release
============================
OK, this is the fun part, where we actually push out a release!
#. Check `Jenkins`__ is green for the version(s) you're putting out. You
probably shouldn't issue a release until it's green.
__ http://djangoci.com
#. A release always begins from a release branch, so you should make sure
you're on a stable branch and up-to-date. For example::
$ git checkout stable/1.5.x
$ git pull
#. If this is a security release, merge the appropriate patches from
``django-private``. Rebase these patches as necessary to make each one a
simple commit on the release branch rather than a merge commit. To ensure
this, merge them with the ``--ff-only`` flag; for example::
$ git checkout stable/1.5.x
$ git merge --ff-only security/1.5.x
(This assumes ``security/1.5.x`` is a branch in the ``django-private`` repo
containing the necessary security patches for the next release in the 1.5
series.)
If git refuses to merge with ``--ff-only``, switch to the security-patch
branch and rebase it on the branch you are about to merge it into (``git
checkout security/1.5.x; git rebase stable/1.5.x``) and then switch back and
do the merge. Make sure the commit message for each security fix explains
that the commit is a security fix and that an announcement will follow
(`example security commit`__).
__ https://github.com/django/django/commit/3ef4bbf495cc6c061789132e3d50a8231a89406b
#. For a feature release, remove the ``UNDER DEVELOPMENT`` header at the
top of the release notes and add the release date on the next line. For a
patch release, replace ``*Under Development*`` with the release date. Make
this change on all branches where the release notes for a particular version
are located.
#. Update the version number in ``django/__init__.py`` for the release.
Please see `notes on setting the VERSION tuple`_ below for details
on ``VERSION``.
#. If this is a pre-release package, update the "Development Status" trove
classifier in ``setup.py`` to reflect this. Otherwise, make sure the
classifier is set to ``Development Status :: 5 - Production/Stable``.
#. Tag the release using ``git tag``. For example::
$ git tag --sign --message="Tag 1.5.1" 1.5.1
You can check your work by running ``git tag --verify <tag>``.
#. Push your work, including the tag: ``git push --tags``.
#. Make sure you have an absolutely clean tree by running ``git clean -dfx``.
#. Run ``make -f extras/Makefile`` to generate the release packages. This will
create the release packages in a ``dist/`` directory.
#. Generate the hashes of the release packages::
$ cd dist
$ md5sum *
$ sha1sum *
$ sha256sum *
#. Create a "checksums" file, ``Django-<<VERSION>>.checksum.txt`` containing
the hashes and release information. Start with this template and insert the
correct version, date, GPG key ID (from
``gpg --list-keys --keyid-format LONG``), release URL, and checksums:
.. code-block:: text
This file contains MD5, SHA1, and SHA256 checksums for the source-code
tarball and wheel files of Django <<VERSION>>, released <<DATE>>.
To use this file, you will need a working install of PGP or other
compatible public-key encryption software. You will also need to have
the Django release manager's public key in your keyring; this key has
the ID ``XXXXXXXXXXXXXXXX`` and can be imported from the MIT
keyserver. For example, if using the open-source GNU Privacy Guard
implementation of PGP:
gpg --keyserver pgp.mit.edu --recv-key XXXXXXXXXXXXXXXX
Once the key is imported, verify this file::
gpg --verify <>
Once you have verified this file, you can use normal MD5, SHA1, or SHA256
checksumming applications to generate the checksums of the Django
package and compare them to the checksums listed below.
Release packages:
=================
https://www.djangoproject.com/m/releases/<<RELEASE TAR.GZ FILENAME>>
https://www.djangoproject.com/m/releases/<<RELEASE WHL FILENAME>>
MD5 checksums:
==============
<<MD5SUM>> <<RELEASE TAR.GZ FILENAME>>
<<MD5SUM>> <<RELEASE WHL FILENAME>>
SHA1 checksums:
===============
<<SHA1SUM>> <<RELEASE TAR.GZ FILENAME>>
<<SHA1SUM>> <<RELEASE WHL FILENAME>>
SHA256 checksums:
=================
<<SHA256SUM>> <<RELEASE TAR.GZ FILENAME>>
<<SHA256SUM>> <<RELEASE WHL FILENAME>>
#. Sign the checksum file (``gpg --clearsign --digest-algo SHA256
Django-<version>.checksum.txt``). This generates a signed document,
``Django-<version>.checksum.txt.asc`` which you can then verify using ``gpg
--verify Django-<version>.checksum.txt.asc``.
If you're issuing multiple releases, repeat these steps for each release.
Making the release(s) available to the public
=============================================
Now you're ready to actually put the release out there. To do this:
#. Upload the release package(s) to the djangoproject server, replacing
A.B. with the appropriate version number, e.g. 1.5 for a 1.5.x release::
$ scp Django-* djangoproject.com:/home/www/www/media/releases/A.B
#. Upload the checksum file(s)::
$ scp Django-A.B.C.checksum.txt.asc djangoproject.com:/home/www/www/media/pgp/Django-A.B.C.checksum.txt
#. Test that the release packages install correctly using ``easy_install``
and ``pip``. Here's one method (which requires `virtualenvwrapper`__)::
$ RELEASE_VERSION='1.7.2'
$ MAJOR_VERSION=`echo $RELEASE_VERSION| cut -c 1-3`
$ mktmpenv
$ easy_install https://www.djangoproject.com/m/releases/$MAJOR_VERSION/Django-$RELEASE_VERSION.tar.gz
$ deactivate
$ mktmpenv
$ pip install https://www.djangoproject.com/m/releases/$MAJOR_VERSION/Django-$RELEASE_VERSION.tar.gz
$ deactivate
$ mktmpenv
$ pip install https://www.djangoproject.com/m/releases/$MAJOR_VERSION/Django-$RELEASE_VERSION-py2.py3-none-any.whl
$ deactivate
This just tests that the tarballs are available (i.e. redirects are up) and
that they install correctly, but it'll catch silly mistakes.
__ https://pypi.python.org/pypi/virtualenvwrapper
#. Ask a few people on IRC to verify the checksums by visiting the checksums
file (e.g. https://www.djangoproject.com/m/pgp/Django-1.5b1.checksum.txt)
and following the instructions in it. For bonus points, they can also unpack
the downloaded release tarball and verify that its contents appear to be
correct (proper version numbers, no stray ``.pyc`` or other undesirable
files).
#. Upload the release packages to PyPI (for pre-releases, only upload the wheel
file)::
$ twine upload -s dist/*
#. Go to the `Add release page in the admin`__, enter the new release number
exactly as it appears in the name of the tarball (Django-<version>.tar.gz).
So for example enter "1.5.1" or "1.4c2", etc. If the release is part of
an LTS branch, mark it so.
__ https://www.djangoproject.com/admin/releases/release/add/
#. Make the blog post announcing the release live.
#. For a new version release (e.g. 1.5, 1.6), update the default stable version
of the docs by flipping the ``is_default`` flag to ``True`` on the
appropriate ``DocumentRelease`` object in the ``docs.djangoproject.com``
database (this will automatically flip it to ``False`` for all
others); you can do this using the site's admin.
#. Post the release announcement to the |django-announce|, |django-developers|,
and |django-users| mailing lists. This should include a link to the
announcement blog post. If this is a security release, also include
[email protected].
#. Add a link to the blog post in the topic of the #django IRC channel:
``/msg chanserv TOPIC #django new topic goes here``.
Post-release
============
You're almost done! All that's left to do now is:
#. Update the ``VERSION`` tuple in ``django/__init__.py`` again,
incrementing to whatever the next expected release will be. For
example, after releasing 1.5.1, update ``VERSION`` to
``VERSION = (1, 5, 2, 'alpha', 0)``.
#. Add the release in `Trac's versions list`_ if necessary (and make it the
default if it's a final release). Not all versions are declared;
take example on previous releases.
#. If this was a security release, update :doc:`/releases/security` with
details of the issues addressed.
.. _Trac's versions list: https://code.djangoproject.com/admin/ticket/versions
New stable branch tasks
=======================
There are several items to do in the time following the creation of a new
stable branch (often following an alpha release). Some of these tasks don't
need to be done by the releaser.
#. Create a new ``DocumentRelease`` object in the ``docs.djangoproject.com``
database for the new version's docs, and update the
``docs/fixtures/doc_releases.json`` JSON fixture, so people without access
to the production DB can still run an up-to-date copy of the docs site.
#. Create a stub release note for the new feature version. Use the stub from
the previous feature release version or copy the contents from the previous
feature version and delete most of the contents leaving only the headings.
#. Increase the default PBKDF2 iterations in
``django.contrib.auth.hashers.PBKDF2PasswordHasher`` by about 20%
(pick a round number). Run the tests, and update the 3 failing
hasher tests with the new values. Make sure this gets noted in the
release notes (see the 1.8 release notes for an example).
#. Remove features that have reached the end of their deprecation cycle. Each
removal should be done in a separate commit for clarity. In the commit
message, add a "refs #XXXX" to the original ticket where the deprecation
began if possible.
#. Remove ``.. versionadded::``, ``.. versionadded::``, and ``.. deprecated::``
annotations in the documentation from two releases ago. For example, in
Django 1.9, notes for 1.7 will be removed.
#. Add the new branch to `Read the Docs
<https://readthedocs.org/projects/django/>`_. Since the automatically
generated version names ("stable-A.B.x") differ from the version numbers
we've used historically in Read the Docs ("A.B.x"), we currently ask Eric
Holscher to add the version for us. Someday the alias functionality may be
built-in to the Read the Docs UI.
Notes on setting the VERSION tuple
==================================
Django's version reporting is controlled by the ``VERSION`` tuple in
``django/__init__.py``. This is a five-element tuple, whose elements
are:
#. Major version.
#. Minor version.
#. Micro version.
#. Status -- can be one of "alpha", "beta", "rc" or "final".
#. Series number, for alpha/beta/RC packages which run in sequence
(allowing, for example, "beta 1", "beta 2", etc.).
For a final release, the status is always "final" and the series
number is always 0. A series number of 0 with an "alpha" status will
be reported as "pre-alpha".
Some examples:
* ``(1, 2, 1, 'final', 0)`` → "1.2.1"
* ``(1, 3, 0, 'alpha', 0)`` → "1.3 pre-alpha"
* ``(1, 3, 0, 'beta', 2)`` → "1.3 beta 2"
---
### 大一小学期 Week 3 Python Exam 2016 Docs Internals Index (`大一小学期/Week_3-Python/exam/2016/docs/internals/index.txt`)
================
Django internals
================
Documentation for people hacking on Django itself. This is the place to go if
you'd like to help improve Django or learn about how Django is managed.
.. toctree::
:maxdepth: 2
contributing/index
mailing-lists
organization
team
roles
security
release-process
deprecation
git
howto-release-django
---
### 大一小学期 Week 3 Python Exam 2016 Docs Internals Mailing Lists (`大一小学期/Week_3-Python/exam/2016/docs/internals/mailing-lists.txt`)
=============
Mailing lists
=============
.. Important::
Please report security issues **only** to
[email protected]. This is a private list only open to
long-time, highly trusted Django developers, and its archives are
not public. For further details, please see :doc:`our security
policies `.
Django has several official mailing lists on Google Groups that are open to
anyone.
.. _django-users-mailing-list:
``django-users``
================
This is the right place if you are looking to ask any question regarding the
installation, usage, or debugging of Django.
.. note::
If it's the first time you send an email to this list, your email must be
accepted first so don't worry if :ref:`your message does not appear
<message-does-not-appear-on-django-users>` instantly.
* `django-users mailing archive`_
* `django-users subscription email address`_
* `django-users posting email`_
.. _django-users mailing archive: https://groups.google.com/d/forum/django-users
.. _django-users subscription email address: mailto:[email protected]
.. _django-users posting email: mailto:[email protected]
.. _django-core-mentorship-mailing-list:
``django-core-mentorship``
==========================
The Django Core Mentorship list is intended to provide a welcoming
introductory environment for community members interested in contributing to
the Django Project.
* `django-core-mentorship mailing archive`_
* `django-core-mentorship subscription email address`_
* `django-core-mentorship posting email`_
.. _django-core-mentorship mailing archive: https://groups.google.com/d/forum/django-core-mentorship
.. _django-core-mentorship subscription email address: mailto:[email protected]
.. _django-core-mentorship posting email: mailto:[email protected]
.. _django-developers-mailing-list:
``django-developers``
=====================
The discussion about the development of Django itself takes place here.
.. note::
Please make use of
:ref:`django-users mailing list <django-users-mailing-list>` if you want
to ask for tech support, doing so in this list is inappropriate.
* `django-developers mailing archive`_
* `django-developers subscription email address`_
* `django-developers posting email`_
.. _django-developers mailing archive: https://groups.google.com/d/forum/django-developers
.. _django-developers subscription email address: mailto:[email protected]
.. _django-developers posting email: mailto:[email protected]
.. _django-i18n-mailing-list:
``django-i18n``
===============
This is the place to discuss the internationalization and localization of
Django's components.
* `django-i18n mailing archive`_
* `django-i18n subscription email address`_
* `django-i18n posting email`_
.. _django-i18n mailing archive: https://groups.google.com/d/forum/django-i18n
.. _django-i18n subscription email address: mailto:[email protected]
.. _django-i18n posting email: mailto:[email protected]
.. _django-announce-mailing-list:
``django-announce``
===================
A (very) low-traffic list for announcing new releases of Django and important
bugfixes.
* `django-announce mailing archive`_
* `django-announce subscription email address`_
* `django-announce posting email`_
.. _django-announce mailing archive: https://groups.google.com/d/forum/django-announce
.. _django-announce subscription email address: mailto:[email protected]
.. _django-announce posting email: mailto:[email protected]
.. _django-updates-mailing-list:
``django-updates``
==================
All the ticket updates are mailed automatically to this list, which is tracked
by developers and interested community members.
* `django-updates mailing archive`_
* `django-updates subscription email address`_
* `django-updates posting email`_
.. _django-updates mailing archive: https://groups.google.com/d/forum/django-updates
.. _django-updates subscription email address: mailto:[email protected]
.. _django-updates posting email: mailto:[email protected]
---
### 大一小学期 Week 3 Python Exam 2016 Docs Internals Organization (`大一小学期/Week_3-Python/exam/2016/docs/internals/organization.txt`)
==================================
Organization of the Django Project
==================================
Principles
==========
The Django Project is managed by a team of volunteers pursuing three goals:
- Driving the development of the Django Web Framework,
- Fostering the ecosystem of Django-related software,
- Leading the Django community in accordance with the values described in the
`Django Code of Conduct`_.
The Django Project isn't a legal entity. The `Django Software Foundation`_, a
non-profit organization, handles financial and legal matters related to the
Django Project. Other than that, the Django Software Foundation lets the
Django Project manage the development of the Django framework, its ecosystem
and its community.
.. _Django Code of Conduct: https://www.djangoproject.com/conduct/
.. _Django Software Foundation: https://www.djangoproject.com/foundation/
The Django core team makes the decisions, nominates its new members, and
elects its technical board. While it holds decision power in theory, it aims
at using it as rarely as possible in practice. Rough consensus should be the
norm and formal voting an exception.
.. _core-team:
Core team
=========
Role
----
The core team is the group of trusted volunteers who manage the Django
Project. They assume many roles required to achieve the project's goals,
especially those that require a high level of trust. They make the decisions
that shape the future of the project.
Core team members are expected to act as role models for the community and
custodians of the project, on behalf of the community and all those who rely
on Django.
They will intervene, where necessary, in online discussions or at official
Django events on the rare occasions that a situation arises that requires
intervention.
They have authority over the Django Project infrastructure, including the
Django Project website itself, the Django GitHub organization and
repositories, the Trac bug tracker, the mailing lists, IRC channels, etc.
Prerogatives
------------
Core team members may participate in formal votes, typically to nominate new
team members and to elect the technical board.
Some contributions don't require commit access. Depending on the reasons why a
contributor joins the team, they may or may not have commit permissions to the
Django code repository.
However, should the need arise, any team member may ask for commit access by
writing to the core team's mailing list. Access will be granted unless the
person withdraws their request or the technical board vetoes the proposal.
Core team members who have commit access are referred to as "committers" or
"core developers".
Other permissions, such as access to the servers, are granted to those who
need them through the same process.
Membership
----------
The core team finds its origins with the :ref:`four people
<original-team-list>` who created Django. It has grown to :ref:`a few dozen
people <core-team-list>` by co-opting volunteers who demonstrate:
- a good grasp of the philosophy of the Django Project
- a solid track record of being constructive and helpful
- significant contributions to the project's goals, in any form
- willingness to dedicate some time to improving Django
As the project matures, contributions go way beyond code. Here's an incomplete
list of areas where contributions may be considered for joining the core team,
in no particular order:
- Working on community management and outreach
- Providing support on the mailing-lists and on IRC
- Triaging tickets
- Writing patches (code, docs, or tests)
- Reviewing patches (code, docs, or tests)
- Participating in design decisions
- Providing expertise in a particular domain (security, i18n, etc.)
- Managing the continuous integration infrastructure
- Managing the servers (website, tracker, documentation, etc.)
- Maintaining related projects (djangoproject.com site, ex-contrib apps, etc.)
- Creating visual designs
Very few areas are reserved to core team members:
- Reviewing security reports
- Merging patches (code, docs, or tests)
- Packaging releases
Core team membership acknowledges sustained and valuable efforts that align
well with the philosophy and the goals of the Django Project.
It is granted by a four fifths majority of votes cast in a core team vote and
no veto by the technical board.
Core team members are always looking for promising contributors, teaching them
how the project is managed, and submitting their names to the core team's vote
when they're ready. If you would like to join the core team, you can contact a
core team member privately or ask for guidance on the :ref:`Django Core
Mentorship mailing-list <django-core-mentorship-mailing-list>`.
There's no time limit on core team membership. However, in order to provide
the general public with a reasonable idea of how many people maintain Django,
core team members who have stopped contributing are encouraged to declare
themselves as "past team members". Those who haven't made any non-trivial
contribution in two years may be asked to move themselves to this category,
and moved there if they don't respond. Past team members lose their privileges
such as voting rights and commit access.
.. _technical-board:
Technical board
===============
Role
----
The technical board is a group of experienced and active committers who steer
technical choices. Their main concern is to maintain the quality and stability
of the Django Web Framework.
Prerogatives
------------
The technical board holds two prerogatives:
- Making major technical decisions when no consensus is found otherwise. This
happens on the |django-developers| mailing-list.
- Veto a grant of commit access or remove commit access. This happens on the
django-core mailing-list.
In both cases, the technical board is a last resort. In these matters, it
fulfills a similar function to the former Benevolent Dictators For Life.
When the board wants to exercise one of these prerogatives, it must hold a
private, simple majority vote on the resolution. The quorum is the full
committee — each member must cast a vote or abstain explicitly. Then the board
communicates the result, and if possible the reasons, on the appropriate
mailing-list. There's no appeal for such decisions.
In addition, at its discretion, the technical board may act in an advisory
capacity on non-technical decisions.
Membership
----------
The technical board is an elected group of five committers. They're expected
to be experienced but there's no formal seniority requirement. Its current
composition is published :ref:`here <technical-board-list>`.
A new board is elected after each feature release of Django. The election
process is managed by a returns officer nominated by the outgoing technical
board. The election process works as follows:
1. Candidates advertise their application for the technical board to the team.
They must be committers already. There's no term limit for technical board
members.
2. Each team member can vote for zero to five people among the candidates.
Candidates are ranked by the total number of votes they received.
In case of a tie, the person who joined the core team earlier wins.
Both the application and the voting period last between one and two weeks, at
the outgoing board's discretion.
Changing the organization
=========================
Changes to this document require a four fifths majority of votes cast in a
core team vote and no veto by the technical board.
---
### 大一小学期 Week 3 Python Exam 2016 Docs Internals Release Process (`大一小学期/Week_3-Python/exam/2016/docs/internals/release-process.txt`)
========================
Django's release process
========================
.. _official-releases:
Official releases
=================
Since version 1.0, Django's release numbering works as follows:
* Versions are numbered in the form ``A.B`` or ``A.B.C``.
* ``A.B`` is the *feature release* version number. Each version will be mostly
backwards compatible with the previous release. Exceptions to this rule will
be listed in the release notes.
* ``C`` is the *patch release* version number, which is incremented for bugfix
and security releases. These releases will be 100% backwards-compatible with
the previous patch release. The only exception is when a security or data
loss issue can't be fixed without breaking backwards-compatibility. If this
happens, the release notes will provide detailed upgrade instructions.
* Before a new feature release, we'll make alpha, beta, and release candidate
releases. These are of the form ``A.B alpha/beta/rc N``, which means the
``Nth`` alpha/beta/release candidate of version ``A.B``.
In git, each Django release will have a tag indicating its version number,
signed with the Django release key. Additionally, each release series has its
own branch, called ``stable/A.B.x``, and bugfix/security releases will be
issued from those branches.
For more information about how the Django project issues new releases for
security purposes, please see :doc:`our security policies <security>`.
.. glossary::
Feature release
Feature releases (A.B, A.B+1, etc.) will happen roughly every eight months
-- see `release process`_ for details. These releases will contain new
features, improvements to existing features, and such.
Patch release
Patch releases (A.B.C, A.B.C+1, etc.) will be issued as needed, to fix
bugs and/or security issues.
These releases will be 100% compatible with the associated feature release,
unless this is impossible for security reasons or to prevent data loss.
So the answer to "should I upgrade to the latest patch release?" will always
be "yes."
Long-term support release
Certain feature releases will be designated as long-term support (LTS)
releases. These releases will get security and data loss fixes applied for
a guaranteed period of time, typically three years.
See `the download page`_ for the releases that have been designated for
long-term support.
.. _the download page: https://www.djangoproject.com/download/
Release cadence
===============
Starting with Django 2.0, version numbers will use a loose form of `semantic
versioning <http://semver.org/>`_ such that each version following an LTS will
bump to the next "dot zero" version. For example: 2.0, 2.1, 2.2 (LTS), 3.0,
3.1, 3.2 (LTS), etc.
SemVer makes it easier to see at a glance how compatible releases are with each
other. It also helps to anticipate when compatibility shims will be removed.
It's not a pure form of SemVer as each feature release will continue to have a
few documented backwards incompatibilities where a deprecation path isn't
possible or not worth the cost. Also, deprecations started in an LTS release
(X.2) will be dropped in a non-dot-zero release (Y.1) to accommodate our policy
of keeping deprecation shims for at least two feature releases. Read on to the
next section for an example.
.. _internal-release-deprecation-policy:
Deprecation policy
==================
A feature release may deprecate certain features from previous releases. If a
feature is deprecated in feature release A.x, it will continue to work in all
A.x versions (for all versions of x) but raise warnings. Deprecated features
will be removed in the B.0 release, or B.1 for features deprecated in the last
A.x feature release to ensure deprecations are done over at least 2 feature
releases.
So, for example, if we decided to start the deprecation of a function in
Django 4.2:
* Django 4.2 will contain a backwards-compatible replica of the function which
will raise a ``RemovedInDjango51Warning``.
* Django 5.0 (the version that follows 4.2) will still contain the
backwards-compatible replica.
* Django 5.1 will remove the feature outright.
The warnings are silent by default. You can turn on display of these warnings
with the ``python -Wd`` option.
A more generic example:
* X.0
* X.1
* X.2 LTS
* Y.0: Drop deprecation shims added in X.0 and X.1.
* Y.1: Drop deprecation shims added in X.2.
* Y.2 LTS: No deprecation shims dropped (while Y.0 is no longer supported,
third-party apps need to maintain compatibility back to X.2 LTS to ease
LTS to LTS upgrades).
* Z.0: Drop deprecation shims added in Y.0 and Y.1.
.. _backwards-compatibility-policy:
Supported versions
==================
At any moment in time, Django's developer team will support a set of releases to
varying levels. See `the supported versions section
<https://www.djangoproject.com/download/#supported-versions>`_ of the download
page for the current state of support for each version.
* The current development master will get new features and bug fixes
requiring non-trivial refactoring.
* Patches applied to the master branch must also be applied to the last feature
release branch, to be released in the next patch release of that feature
series, when they fix critical problems:
* Security issues.
* Data loss bugs.
* Crashing bugs.
* Major functionality bugs in newly-introduced features.
* Regressions from older versions of Django.
The rule of thumb is that fixes will be backported to the last feature
release for bugs that would have prevented a release in the first place
(release blockers).
* Security fixes and data loss bugs will be applied to the current master, the
last two feature release branches, and any other supported long-term
support release branches.
* Documentation fixes generally will be more freely backported to the last
release branch. That's because it's highly advantageous to have the docs for
the last release be up-to-date and correct, and the risk of introducing
regressions is much less of a concern.
As a concrete example, consider a moment in time halfway between the release of
Django 5.1 and 5.2. At this point in time:
* Features will be added to development master, to be released as Django 5.2.
* Critical bug fixes will be applied to the ``stable/5.1.x`` branch, and
released as 5.1.1, 5.1.2, etc.
* Security fixes and bug fixes for data loss issues will be applied to
``master`` and to the ``stable/5.1.x``, ``stable/5.0.x``, and
``stable/4.2.x`` (LTS) branches. They will trigger the release of ``5.1.1``,
``5.0.5``, ``4.2.8``, etc.
* Documentation fixes will be applied to master, and, if easily backported, to
the latest stable branch, ``5.1.x``.
.. _release-process:
Release process
===============
Django uses a time-based release schedule, with feature releases every eight
months or so.
After each feature release, the release manager will announce a timeline for
the next feature release.
Release cycle
-------------
Each release cycle consists of three parts:
Phase one: feature proposalThe first phase of the release process will include figuring out what major
features to include in the next version. This should include a good deal of
preliminary work on those features -- working code trumps grand design.
Major features for an upcoming release will be added to the wiki roadmap page,
e.g. https://code.djangoproject.com/wiki/Version1.9Roadmap.
Phase two: development
The second part of the release schedule is the "heads-down" working period.
Using the roadmap produced at the end of phase one, we'll all work very hard to
get everything on it done.
At the end of phase two, any unfinished features will be postponed until the
next release.
Phase two will culminate with an alpha release. At this point, the
``stable/A.B.x`` branch will be forked from ``master``.
Phase three: bugfixes
~~~~~~~~~~~~~~~~~~~~~
The last part of a release cycle is spent fixing bugs -- no new features will
be accepted during this time. We'll try to release a beta release one month
after the alpha and a release candidate one month after the beta.
The release candidate marks the string freeze, and it happens at least two
weeks before the final release. After this point, new translatable strings
must not be added.
During this phase, committers will be more and more conservative with
backports, to avoid introducing regressions. After the release candidate, only
release blockers and documentation fixes should be backported.
In parallel to this phase, ``master`` can receive new features, to be released
in the ``A.B+1`` cycle.
Bug-fix releases
----------------
After a feature release (e.g. A.B), the previous release will go into bugfix
mode.
The branch for the previous feature release (e.g. ``stable/A.B-1.x``) will
include bugfixes. Critical bugs fixed on master must *also* be fixed on the
bugfix branch; this means that commits need to cleanly separate bug fixes from
feature additions. The developer who commits a fix to master will be
responsible for also applying the fix to the current bugfix branch.
---
### 大一小学期 Week 3 Python Exam 2016 Docs Internals Roles (`大一小学期/Week_3-Python/exam/2016/docs/internals/roles.txt`)
=====
Roles
=====
.. _technical-board-list:
Technical board
===============
The technical board for the 1.10 release cycle is:
* James Bennett
* Andrew Godwin
* Russell Keith-Magee
* Carl Meyer
* Marc Tamlyn
.. _committers:
Committers
==========
Most :ref:`core team <core-team>` members have commit access. They're called
"committers" or "core developers".
Being part of the core team is a pre-requisite for having commit access.
.. _security-team-list:
Security team
=============
The security team is responsible for :doc:`Django's security policies
`. It handles private reports of security issues.
The current security team members are:
- Florian Apolloner
- James Bennett
- Jeremy Dunck
- Adrian Holovaty
- Jacob Kaplan-Moss
- Russell Keith-Magee
- Paul McMillan
- Carl Meyer
- Donald Stufft
.. _releasers-list:
Releasers
=========
Releasers take care of :doc:`building Django releases
`.
The current releasers are:
- James Bennett
- Jacob Kaplan-Moss
- Tim Graham
Ops team
========
The ops team maintains Django's infrastructure like the Django Project server,
Trac instance, and continuous integration infrastructure.
- Florian Apolloner
- Aymeric Augustin
- Tim Graham
- Jannis Leidel
---
### 大一小学期 Week 3 Python Exam 2016 Docs Internals Security (`大一小学期/Week_3-Python/exam/2016/docs/internals/security.txt`)
==========================
Django's security policies
==========================
Django's development team is strongly committed to responsible
reporting and disclosure of security-related issues. As such, we've
adopted and follow a set of policies which conform to that ideal and
are geared toward allowing us to deliver timely security updates to
the official distribution of Django, as well as to third-party
distributions.
.. _reporting-security-issues:
Reporting security issues
=========================
**Short version: please report security issues by emailing
[email protected]**.
Most normal bugs in Django are reported to `our public Trac instance`_, but
due to the sensitive nature of security issues, we ask that they **not** be
publicly reported in this fashion.
Instead, if you believe you've found something in Django which has security
implications, please send a description of the issue via email to
``[email protected]``. Mail sent to that address reaches a
:ref:`subset of the core team <security-team-list>`, who can forward security
issues into the private committers' mailing list for broader discussion if
needed.
Once you've submitted an issue via email, you should receive an acknowledgment
from a member of the security team within 48 hours, and depending on the
action to be taken, you may receive further followup emails.
.. note::
If you want to send an encrypted email (*optional*), the public key ID for
``[email protected]`` is ``0xfcb84b8d1d17f80b``, and this public
key is available from most commonly-used keyservers.
.. _our public Trac instance: https://code.djangoproject.com/query
.. _security-support:
Supported versions
==================
At any given time, the Django team provides official security support
for several versions of Django:
* The `master development branch`_, hosted on GitHub, which will
become the next release of Django, receives security support.
* The two most recent Django release series receive security
support. For example, during the development cycle leading to the
release of Django 1.5, support will be provided for Django 1.4 and
Django 1.3. Upon the release of Django 1.5, Django 1.3's security
support will end.
* :term:`Long-term support release`\s will receive security updates for a
specified period.
When new releases are issued for security reasons, the accompanying
notice will include a list of affected versions. This list is
comprised solely of *supported* versions of Django: older versions may
also be affected, but we do not investigate to determine that, and
will not issue patches or new releases for those versions.
.. _master development branch: https://github.com/django/django/
.. _security-disclosure:
How Django discloses security issues
====================================
Our process for taking a security issue from private discussion to
public disclosure involves multiple steps.
Approximately one week before full public disclosure, we will send
advance notification of the issue to a list of people and
organizations, primarily composed of operating-system vendors and
other distributors of Django. This notification will consist of an
email message, signed with the Django release key, containing:
* A full description of the issue and the affected versions of Django.
* The steps we will be taking to remedy the issue.
* The patch(es), if any, that will be applied to Django.
* The date on which the Django team will apply these patches, issue
new releases and publicly disclose the issue.
Simultaneously, the reporter of the issue will receive notification of
the date on which we plan to take the issue public.
On the day of disclosure, we will take the following steps:
1. Apply the relevant patch(es) to Django's codebase. The commit
messages for these patches will indicate that they are for security
issues, but will not describe the issue in any detail; instead,
they will warn of upcoming disclosure.
2. Issue the relevant release(s), by placing new packages on `the
Python Package Index`_ and on the Django website, and tagging the
new release(s) in Django's git repository.
3. Post a public entry on `the official Django development blog`_,
describing the issue and its resolution in detail, pointing to the
relevant patches and new releases, and crediting the reporter of
the issue (if the reporter wishes to be publicly identified).
4. Post a notice to the |django-announce| and [email protected]
mailing lists that links to the blog post.
.. _the Python Package Index: https://pypi.python.org/pypi
.. _the official Django development blog: https://www.djangoproject.com/weblog/
If a reported issue is believed to be particularly time-sensitive --
due to a known exploit in the wild, for example -- the time between
advance notification and public disclosure may be shortened
considerably.
Additionally, if we have reason to believe that an issue reported to
us affects other frameworks or tools in the Python/web ecosystem, we
may privately contact and discuss those issues with the appropriate
maintainers, and coordinate our own disclosure and resolution with
theirs.
The Django team also maintains an :doc:`archive of security issues
disclosed in Django</releases/security>`.
.. _security-notifications:
Who receives advance notification
=================================
The full list of people and organizations who receive advance
notification of security issues is not and will not be made public.
We also aim to keep this list as small as effectively possible, in
order to better manage the flow of confidential information prior to
disclosure. As such, our notification list is *not* simply a list of
users of Django, and merely being a user of Django is not sufficient
reason to be placed on the notification list.
In broad terms, recipients of security notifications fall into three
groups:
1. Operating-system vendors and other distributors of Django who
provide a suitably-generic (i.e., *not* an individual's personal
email address) contact address for reporting issues with their
Django package, or for general security reporting. In either case,
such addresses **must not** forward to public mailing lists or bug
trackers. Addresses which forward to the private email of an
individual maintainer or security-response contact are acceptable,
although private security trackers or security-response groups are
strongly preferred.
2. On a case-by-case basis, individual package maintainers who have
demonstrated a commitment to responding to and responsibly acting
on these notifications.
3. On a case-by-case basis, other entities who, in the judgment of the
Django development team, need to be made aware of a pending
security issue. Typically, membership in this group will consist of
some of the largest and/or most likely to be severely impacted
known users or distributors of Django, and will require a
demonstrated ability to responsibly receive, keep confidential and
act on these notifications.
Requesting notifications
========================
If you believe that you, or an organization you are authorized to
represent, fall into one of the groups listed above, you can ask to be
added to Django's notification list by emailing
``[email protected]``. Please use the subject line "Security
notification request".
Your request **must** include the following information:
* Your full, real name and the name of the organization you represent,
if applicable, as well as your role within that organization.
* A detailed explanation of how you or your organization fit at least
one set of criteria listed above.
* A detailed explanation of why you are requesting security
notifications. Again, please keep in mind that this is *not* simply
a list for users of Django, and the overwhelming majority of users
of Django should not request notifications and will not be added to
our notification list if they do.
* The email address you would like to have added to our notification
list.
* An explanation of who will be receiving/reviewing mail sent to that
address, as well as information regarding any automated actions that
will be taken (i.e., filing of a confidential issue in a bug
tracker).
* For individuals, the ID of a public key associated with your address
which can be used to verify email received from you and encrypt
email sent to you, as needed.
Once submitted, your request will be considered by the Django
development team; you will receive a reply notifying you of the result
of your request within 30 days.
Please also bear in mind that for any individual or organization,
receiving security notifications is a privilege granted at the sole
discretion of the Django development team, and that this privilege can
be revoked at any time, with or without explanation.
If you are added to the notification list, security-related emails
will be sent to you by Django's release team, and all notification
emails will be signed with a key authorized to issue Django
releases. The list of authorized keys is in `the Django releasers
file`_.
.. _the Django releasers file: https://www.djangoproject.com/m/pgp/django-releasers.txt
---
### 大一小学期 Week 3 Python Exam 2016 Docs Internals Team (`大一小学期/Week_3-Python/exam/2016/docs/internals/team.txt`)
===========
Django team
===========
.. _original-team-list:
The original team
=================
Django originally started at World Online, the Web department of the `Lawrence
Journal-World`_ of Lawrence, Kansas, USA.
`Adrian Holovaty`_
Adrian is a Web developer with a background in journalism. He's known in
journalism circles as one of the pioneers of "journalism via computer
programming", and in technical circles as "the guy who invented Django."
He was lead developer at World Online for 2.5 years, during which time
Django was developed and implemented on World Online's sites. He was the
leader and founder of EveryBlock_, a "news feed for your block." He now
develops Soundslice_.
Adrian lives in Chicago, USA.
`Simon Willison`_
Simon is a well-respected Web developer from England. He had a one-year
internship at World Online, during which time he and Adrian developed Django
from scratch. The most enthusiastic Brit you'll ever meet, he's passionate
about best practices in Web development and maintains a well-read
`web-development blog`_.
Simon lives in Brighton, England.
`Jacob Kaplan-Moss`_
Jacob is Director of Platform Security at Heroku_. He worked at World
Online for four years, where he helped open source Django and found
the Django Software Foundation. Jacob lives on a hobby farm outside of
Lawrence where he spends his weekends playing with dirt and power tools.
`Wilson Miner`_
Wilson's design-fu is what makes Django look so nice. He created the design
that was used for nearly the first ten years on the Django Project website,
as well as the current design for Django's acclaimed admin interface. Wilson
was the designer for EveryBlock and Rdio_. He now designs for Facebook.
Wilson lives in San Francisco, USA.
.. _lawrence journal-world: http://ljworld.com/
.. _adrian holovaty: http://holovaty.com/
.. _everyblock: https://everyblock.com/
.. _soundslice: https://www.soundslice.com/
.. _simon willison: http://simonwillison.net/
.. _web-development blog: `simon willison`_
.. _jacob kaplan-moss: https://jacobian.org/
.. _revolution systems: http://revsys.com/
.. _wilson miner: http://wilsonminer.com/
.. _heroku: https://heroku.com/
.. _Rdio: http://rdio.com
.. _core-team-list:
The current team
================
These are the folks who have a long history of contributions, a solid track
record of being helpful on the mailing lists, and a proven desire to dedicate
serious time to Django. In return, they've been invited to join the :ref:`core
team <core-team>`.
`Luke Plant`_
At University Luke studied physics and Materials Science and also
met `Michael Meeks`_ who introduced him to Linux and Open Source,
re-igniting an interest in programming. Since then he has
contributed to a number of Open Source projects and worked
professionally as a developer.
Luke has contributed many excellent improvements to Django,
including database-level improvements, the CSRF middleware and
many unit tests.
Luke currently works for a church in Bradford, UK, and part-time
as a freelance developer.
.. _luke plant: http://lukeplant.me.uk/
.. _michael meeks: https://en.wikipedia.org/wiki/Michael_Meeks_(software)
`Russell Keith-Magee`_
Russell studied physics as an undergraduate, and studied neural networks for
his PhD. His first job was with a startup in the defense industry developing
simulation frameworks. Over time, mostly through work with Django, he's
become more involved in Web development.
Russell has helped with several major aspects of Django, including a
couple major internal refactorings, creation of the test system, and more.
Russell lives in the most isolated capital city in the world — Perth,
Australia.
.. _russell keith-magee: http://cecinestpasun.com/
`James Bennett`_
James has been one of Django's release managers, and also
contributes to the documentation and provide the occasional
bugfix.
James came to Web development from philosophy when he discovered
that programmers get to argue just as much while collecting much
better pay. He lives in San Mateo, California and previously
worked at World Online and Mozilla; currently, he's part of the
Web engineering team at `Clover`_.
He `keeps a blog`_, and enjoys fine port and talking to his car.
.. _james bennett: http://b-list.org/
.. _Clover: https://www.cloverhealth.com/
.. _keeps a blog: `james bennett`_
Justin Bronn
Justin Bronn is a computer scientist and attorney specializing
in legal topics related to intellectual property and spatial law.
In 2007, Justin began developing ``django.contrib.gis`` in a branch,
a.k.a. GeoDjango_, which was merged in time for Django 1.0. While
implementing GeoDjango, Justin obtained a deep knowledge of Django's
internals including the ORM, the admin, and Oracle support.
Justin lives in Houston, TX.
.. _GeoDjango: http://geodjango.org/
Karen Tracey
Karen has a background in distributed operating systems (graduate school),
communications software (industry) and crossword puzzle construction
(freelance). The last of these brought her to Django, in late 2006, when
she set out to put a Web front-end on her crossword puzzle database.
That done, she stuck around in the community answering questions, debugging
problems, etc. -- because coding puzzles are as much fun as word puzzles.
Karen lives in Apex, NC, USA.
`Jannis Leidel`_
Jannis graduated in media design from `Bauhaus-University Weimar`_,
is the author of a number of pluggable Django apps and likes to
contribute to Open Source projects like virtualenv_ and pip_.
He has worked on Django's auth, admin and staticfiles apps as well as
the form, core, internationalization and test systems. He currently works
at Mozilla_.
Jannis lives in Berlin, Germany.
.. _Jannis Leidel: https://jezdez.com/
.. _Bauhaus-University Weimar: http://www.uni-weimar.de/
.. _virtualenv: http://www.virtualenv.org/
.. _pip: https://pip.pypa.io/
.. _Mozilla: https://www.mozilla.org/
`Andrew Godwin`_
Andrew is a freelance Python developer and tinkerer, and has been
developing against Django since 2007. He graduated from Oxford University
with a degree in Computer Science, and has become most well known
in the Django community for his work on South, the schema migrations
library.
Andrew lives in San Francisco, CA, USA.
.. _Andrew Godwin: https://www.aeracode.org/
`Carl Meyer`_
Carl has been a Django user since 2007 (long enough to remember
queryset-refactor, but not magic-removal), and builds web apps at OddBird_.
He became a Django contributor by accident, because fixing bugs is more
interesting than working around them.
Carl lives in Rapid City, SD, USA.
.. _Carl Meyer: http://www.oddbird.net/
.. _OddBird: http://www.oddbird.net/
Ramiro Morales
Ramiro has been reading Django source code and submitting patches since
mid-2006 after researching for a Python Web tool with matching awesomeness
and being pointed to it by an old ninja.
A software developer in the electronic transactions industry, he is a
living proof of the fact that anyone with enough enthusiasm can contribute
to Django, learning a lot and having fun in the process.
Ramiro lives in Córdoba, Argentina.
`Chris Beaven`_
Chris has been submitting patches and suggesting crazy ideas for Django
since early 2006. An advocate for community involvement and a long-term
triager, he is still often found answering questions in the #django IRC
channel.
Chris lives in Napier, New Zealand (adding to the pool of Oceanic core
developers). He works remotely as a developer for `Lincoln Loop`_.
.. _Chris Beaven: http://smileychris.com/
.. _Lincoln Loop: https://lincolnloop.com/
Honza Král
Honza first discovered Django in 2006 and started using it right away,
first for school and personal projects and later in his full-time job. He
contributed various patches and fixes mostly to the newforms library,
newforms admin and, through participation in the Google Summer of Code
project, assisted in creating the :ref:`model validation
<validating-objects>` functionality.
He is currently working for `Whiskey Media`_ in San Francisco developing
awesome sites running on pure Django.
.. _Whiskey Media: http://www.whiskeymedia.com/
Tim Graham
When exploring Web frameworks for an independent study project in the fall
of 2008, Tim discovered Django and was lured to it by the documentation.
He enjoys contributing to the docs because they're awesome.
Tim works as a software engineer and lives in Philadelphia, PA, USA.
Paul McMillan
Paul found Django in 2008 while looking for a more
structured approach to web programming. He stuck around after
figuring out that the developers of Django had already invented
many of the wheels he needed. His passion for breaking (and then
fixing) things led to his current role working to maintain and
improve the security of Django.
`Julien Phalip`_
Julien has a background in software engineering and human-computer
interaction. As a Web developer, he enjoys tinkering with the backend as
much as designing and coding user interfaces. Julien discovered Django in
2007 while doing his PhD in Computing Sciences. Since then he has
contributed patches to various components of the framework, in particular
the admin. Julien was a co-founder of the `Interaction Consortium`_. He
now works at Odopod_, a digital agency based in San Francisco, CA, USA.
.. _Julien Phalip: http://julienphalip.com
.. _Interaction Consortium: http://interaction.net.au
.. _Odopod: http://odopod.com
`Aymeric Augustin`_
Aymeric is an engineer with a background in mathematics and computer
science. He chose Django because he believes that software should be simple,
explicit and tested. His perfectionist tendencies quickly led him to triage
tickets and contribute patches.
Aymeric has a pragmatic approach to software engineering, can't live without
a continuous integration server, and likes proving that Django is a good
choice for enterprise software.
.. _Aymeric Augustin: https://myks.org/
`Claude Paroz`_
Claude is a former teacher who fell in love with free software at the
beginning of the 21st century. He's now working as freelancer in Web
development in his native Switzerland. He has found in Django a perfect
match for his needs of a stable, clean, documented and well-maintained Web
framework.
He's also helping the GNOME Translation Project as maintainer of the
Django-based `l10n.gnome.org`_.
.. _Claude Paroz: http://www.2xlibre.net
.. _l10n.gnome.org: https://l10n.gnome.org
Anssi Kääriäinen
Anssi works as a developer at Finnish National Institute for Health and
Welfare. He is also a computer science student at Aalto University. In his
work he uses Django for developing internal business applications and sees
Django as a great match for that use case.
Anssi is interested in developing the object relational mapper (ORM) and
all related features. He's also a fan of benchmarking and he tries keep
Django as fast as possible.
Florian Apolloner
Florian is currently studying Physics at the `Graz University of Technology`_.
Soon after he started using Django he joined the `Ubuntuusers webteam`_ to
work on *Inyoka*, the software powering the whole Ubuntuusers site.
For the time being he lives in Graz, Austria (not Australia ;)).
.. _Graz University of Technology: http://tugraz.at/
.. _Ubuntuusers webteam: https://wiki.ubuntuusers.de/ubuntuusers/Webteam
Jeremy Dunck
Jeremy was rescued from corporate IT drudgery by Free Software and, in part,
Django. Many of Jeremy's interests center around access to information.
Jeremy was the lead developer of Pegasus News, one of the first uses of
Django outside World Online, and has since joined Votizen, a startup intent
on reducing the influence of money in politics.
He serves as DSF Secretary, organizes and helps organize sprints, cares
about the health and equity of the Django community. He has gone an
embarrassingly long time without a working blog.
Jeremy lives in Mountain View, CA, USA.
`Bryan Veloso`_
Bryan found Django 0.96 through a fellow designer who was evangelizing
its use. It was his first foray outside of the land that was PHP-based
templating. Although he has only ever used Django for personal projects,
it is the very reason he considers himself a designer/developer
hybrid and is working to further design within the Django community.
Bryan works as a designer at GitHub by day, and masquerades as a `vlogger`_
and `shoutcaster`_ in the after-hours. Bryan lives in Los Angeles, CA, USA.
.. _bryan veloso: http://avalonstar.com/
.. _vlogger: https://youtube.com/bryanveloso/
.. _shoutcaster: http://twitch.tv/vlogalonstar/
`Simon Charette`_
Simon is a mathematics student who discovered Django while searching for a
replacement framework to an in-house PHP entity. Since that faithful day
Django has been a big part of his life. So far, he's been involved in some
ORM and forms API fixes.
Apart from contributing to multiple open source projects he spends most of
his spare-time playing `Ultimate Frisbee`_ and working part-time
at this awesome place called `Reptiletech`_.
Simon lives in Montréal, Québec, Canada.
.. _Simon Charette: https://github.com/charettes
.. _Ultimate Frisbee: http://www.montrealultimate.ca
.. _Reptiletech: https://www.reptiletech.com
Donald Stufft
Donald found Python and Django in 2007 while trying to find a language,
and web framework that he really enjoyed using after many years of PHP. He
fell in love with the beauty of Python and the way Django made tasks simple
and easy. His contributions to Django focus primarily on ensuring that it
is and remains a secure web framework.
Donald currently works at `Nebula Inc`_ as a Software Engineer for their
security team and lives in the Greater Philadelphia Area.
.. _Nebula Inc: https://www.nebula.com/
Marc Tamlyn
Marc started life on the web using Django 1.2 back in 2010, and has never
looked back. He was involved with rewriting the class-based view
documentation at DjangoCon EU 2012, and also helped to develop `CCBV`_, an
additional class-based view reference tool.
Marc is currently a full-time parent, part-time developer, and lives in
Oxford, UK.
.. _CCBV: https://ccbv.co.uk/
Shai Berger
Shai started working with Python back in 1998, and with Django just
before 1.0. He is a Free Software enthusiast, but life happens, and
he was driven by consulting gigs to contribute to the Oracle and
SQL Server backends of South, and then the Oracle backend of Django
itself. Finally, he joined core to help maintain the Oracle backend.
Shai works for `Platonix`_, a small consulting company he started
with a few friends in 1996, and lives near Tel Aviv, Israel.
.. _Platonix: http://tech.platonix.com
Baptiste Mispelon
Baptiste discovered Django around the 1.2 version and promptly switched away
from his homegrown PHP framework. He started getting more involved in the
project after attending DjangoCon EU 2012, mostly by triaging tickets and
submitting small patches.
Baptiste currently lives in Budapest, Hungary and works for `M2BPO`_,
a small French company providing services to architects.
.. _M2BPO: https://www.m2bpo.fr
Daniele Procida
Daniele unexpectedly became a Django developer on 29th April 2009. Since
then he has relied daily on Django's documentation, which has been a
constant companion to him. More recently he has been able to contribute
back to the project by helping improve the documentation itself.
He is the author of `Arkestra`_ and `Don't be afraid to commit`_. He lives
in Cardiff, Wales, and works for `Divio`_.
.. _Divio: https://divio.ch/
.. _Arkestra: http://arkestra-project.org/
.. _Don\'t be afraid to commit: https://dont-be-afraid-to-commit.readthedocs.io
`Erik Romijn`_
Erik started using Django in the days of 1.2. His largest contribution to Django was
``GenericIPAddressField``, and he has worked on all sorts of patches since.
While developing with Django, he always keeps a little list of even the slightest
Django frustrations, to tackle them at a later time and prevent other developers
from having to deal with the same issues.
Erik is an independent app maker, mostly developing web and mobile apps, as
`Solid Links`_. He also enjoys helping ordinary developers to build safer web apps,
for which Django is already a great start, and developed `Erik's Pony Checkup`_ with
that goal in mind. Erik lives in Amsterdam, The Netherlands.
.. _Erik Romijn: http://erik.io/
.. _Solid Links: https://solidlinks.nl/
.. _Erik's Pony Checkup: https://ponycheckup.com/
`Loïc Bistuer`_
Loïc studied telecommunications engineering and works as an independent
software developer and consultant.
He discovered Django in 2008 shortly before the 1.0 release and has been
hooked ever since. He contributes mostly to Django's ORM and Form
components. His main contributions include advanced query prefetching,
streamlining QuerySet and Manager to improve query reusability, and a
significant refactor of forms error handling.
Loïc is originally from the South of France and currently lives in
Bangkok, Thailand.
.. _Loïc Bistuer: https://github.com/loic
`Michael Manfre`_
Michael started running Django on Windows against a Microsoft SQL Server
(MSSQL) database in 2008. He quickly became the maintainer of the
django-mssql 3rd party database backend. Much of his involvement with
Django relates to the ORM, the private 3rd party database API, and using
Django on Windows.
Michael lives in Cary, NC, USA.
.. _Michael Manfre: http://manfre.net
`Collin Anderson`_
Collin found Django in November 2006. He was in awe of the admin and ORM
and was amazed that the documentation was teaching him best web practices
like redirecting after a successful POST request. Why had he never learned
this before? No one knows to this day.
He enjoys helping people on the |django-users| mailing list and making
Django simple and easy for newcomers.
Collin lives in South Bend, IN, USA where he uses Django to `increase
unity`_.
.. _Collin Anderson: https://github.com/collinanderson
.. _increase unity: http://onetencommunications.com/about/
`Tom Christie`_
Tom has background in speech recognition, networking, and web development.
He has a particular interest in Web API design and is the original author
of `Django REST framework`_.
Tom lives in the seaside city of Brighton, UK.
.. _Tom Christie: https://twitter.com/_tomchristie
.. _Django REST framework: http://django-rest-framework.org
`Curtis Maloney`_
Curtis is a self-taught programmer from Melbourne, Australia, who eschews
specialization. Upon finding Django when it was first open sourced, he
realized it was possible to enjoy web development.
He spends a lot of time helping people on the #django IRC channel, and has
authored and released a number of `smaller django apps`_.
.. _Curtis Maloney: http://musings.tinbrain.net/blog/
.. _smaller django apps: https://github.com/funkybob/
`Markus Holtermann`_
Markus is a senior backend developer at `LaterPay`_ in Munich. He studied
Computer Science at the `Technical University of Berlin`_. He started
working with Django in 2010 when he joined the `ubuntuusers.de`_ web team
to work on *Inyoka*. Markus made his first contribution to the Django
project during DjangoCon Europe 2013 in Warsaw. He was the web team leader
for the `EuroPython 2014 website`_ and started regular contributions to
Django after that.
Markus lives in Berlin, Germany.
.. _Markus Holtermann: https://github.com/MarkusH
.. _LaterPay: https://www.laterpay.net/
.. _Technical University of Berlin: http://www.tu-berlin.de/
.. _ubuntuusers.de: https://ubuntuusers.de/
.. _EuroPython 2014 website: https://ep2014.europython.eu/
`Josh Smeaton`_
Josh was given the opportunity to work on a new Django app around version
1.1 after working with a homegrown PHP reporting framework. The simplicity
of the ORM and the power of the Admin were extremely liberating.
Still being involved with custom reporting applications, he decided to try
his hand at improving the ORM support for analytics. His contributions
focus on giving more power to users of the ORM.
Josh lives in Melbourne, Australia where he heads up development for a SaaS
telecommunications company.
.. _Josh Smeaton: https://github.com/jarshwah
`Preston Timmons`_
Preston is a software developer with a background in mathematics. He enjoys
Django because it enables consistent, simple, and tested systems to be
built that even new programmers can quickly dive into. Preston lives in
Dallas, TX.
.. _Preston Timmons: https://github.com/prestontimmons
`Tomek Paczkowski`_
Tomek started using Django in 2007 as a tool for quickly dealing with
university projects. Since then, he worked with various technologies
like Ruby on Rails, JavaScript and Android but always returned to
Python and Django.
Tomek loves the Django community. He organized multiple Django
sprints, co-organized `DjangoCon Europe 2013`_ and has mentored at many
`Django Girls`_ events.
Originally from Poland, Tomek currently lives in London, where he
works at Squirrel_.
.. _Tomek Paczkowski: https://hauru.eu
.. _DjangoCon Europe 2013: http://love.djangocircus.com
.. _Django Girls: https://djangogirls.org
.. _Squirrel: https://squirrel.me
`Ola Sitarska`_
Ola started working with Django in 2009, when she discovered the power of
the Django admin and quickly fell in love with the beauty of Python.
She co-organized `DjangoCon Europe 2013`_ in Warsaw and co-authored the
`Django Girls Tutorial`_, the most beginner friendly Django tutorial out
there. Together with Ola Sendecka, she started `Django Girls`_, a community
and series of Django workshops for women who've never programmed before.
In 2015, she became a Django Software Foundation board member. Ola was also
a part of the team responsible for shipping the djangoproject.com redesign.
Originally from Poland, Ola currently lives in London, where she
works with friends at `Potato`_.
.. _Ola Sitarska: http://ola.sitarska.com/
.. _DjangoCon Europe 2013: http://love.djangocircus.com
.. _Django Girls Tutorial: http://tutorial.djangogirls.org
.. _Django Girls: https://djangogirls.org
.. _Potato: https://p.ota.to
`Ola Sendecka`_
Ola started her adventure with Django when writing a university project in
2009. After that she attended her first DjangoCon Europe which
defined her future life as a Django professional.
Since then she has been an active community member. Ola co-organized a number of
Django sprints and conferences including:
`DjangoCon Europe 2013`_, `Django Under the Hood 2015`_ and
`DjangoCon Europe 2016`_. Together with Ola Sitarska she founded
`Django Girls`_, co-authored the `Django Girls Tutorial`_ and
is a member of the Django Girls Foundation. She is also an author of
the `Coding is for Girls`_ YouTube series teaching programming and Django
to beginners.
Originally from Poland, Ola currently lives in London, where she works for `Potato`_.
.. _Ola Sendecka: https://twitter.com/asendecka
.. _DjangoCon Europe 2013: http://love.djangocircus.com
.. _Django Under the Hood 2015: http://www.djangounderthehood.com/
.. _DjangoCon Europe 2016: http://2016.djangocon.eu
.. _Django Girls: https://djangogirls.org
.. _Django Girls Tutorial: http://tutorial.djangogirls.org
.. _Coding is for Girls: https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A
.. _Potato: https://p.ota.to
Past team members
=================
Georg "Hugo" Bauer
Georg created Django's internationalization system, managed i18n
contributions and made a ton of excellent tweaks, feature additions and bug
fixes.
Robert Wittams
Robert was responsible for the *first* refactoring of Django's admin
application to allow for easier reuse and has made a ton of
excellent tweaks, feature additions and bug fixes.
`Alex Gaynor`_
Alex was involved in many parts of Django, he contributed to the ORM,
forms, admin, amongst others; he is most known for his work on
multiple-database support in Django.
Alex lives in Washington, DC, USA.
.. _Alex Gaynor: https://alexgaynor.net
`Simon Meers`_
Simon discovered Django 0.96 during his Computer Science PhD research and
has been developing with it full-time ever since. His core code
contributions are mostly in Django's admin application.
Simon works as a freelance developer based in Wollongong, Australia.
.. _Simon Meers: http://simonmeers.com/
`Gabriel Hurley`_
Gabriel has been working with Django since 2008, shortly after the 1.0
release. Convinced by his business partner that Python and Django were the
right direction for the company, he couldn't have been more happy with the
decision. His contributions range across many areas in Django, but years of
copy-editing and an eye for detail lead him to be particularly at home
while working on Django's documentation.
Gabriel works as a developer in the SF Bay Area, CA, USA.
.. _gabriel hurley: http://strikeawe.com/
Malcolm Tredinnick
Malcolm originally wanted to be a mathematician and somehow ended up a
software developer. He contributed to many Open Source projects, served on
the board of the GNOME foundation, and was a great chess player.
Malcolm was deeply involved in many part of Django - most notably, the
ORM, but many other internals bear his fingerprints. Django’s support for
unicode and autoescaping in templates can both be almost entirely
attributed to Malcolm.
He was an International Man of Mystery and lived in Sydney, Australia.
*Malcolm passed away on March 17, 2013.*
`Preston Holmes`_
Preston is a recovering neuroscientist who originally discovered Django as
part of a sweeping move to Python from a grab bag of half a dozen
languages. He was drawn to Django's balance of practical batteries included
philosophy, care and thought in code design, and strong open source
community. Currently working in the rent-your-infra space (aka Cloud), he
is always looking for opportunities to volunteer for community oriented
education projects, such as for kids and scientists (e.g. Software
Carpentry).
Preston lives with his family and animal menagerie in Santa Barbara, CA, USA.
.. _Preston Holmes: http://www.ptone.com/
`Idan Gazit`_
As a self-professed design geek, Idan was initially attracted to Django
sometime between magic-removal and queryset-refactor. Formally trained
as a software engineer, Idan straddles the worlds of design and code,
jack of two trades and master of none. He is passionate about usability
and finding novel ways to extract meaning from data, and is a longtime
photographer_.
Idan is currently hacking on all things data and visualization at Heroku_.
.. _Idan Gazit: http://gazit.me
.. _photographer: https://flickr.com/photos/idangazit
Matt Boersma
Matt helped with Django's Oracle support.
Ian Kelly
Ian also helped with Oracle support.
Joseph Kocherhans
Joseph was the director of lead development at EveryBlock and previously
developed at the Lawrence Journal-World. He often disappears for several
days into the woods, attempts to teach himself computational linguistics,
and annoys his neighbors with his Charango_ playing.
Joseph's first contribution to Django was a series of improvements to the
authorization system leading up to support for pluggable authorization.
Since then, he's worked on the new forms system, its use in the admin, and
many other smaller improvements.
Joseph lives in Chicago, USA.
.. _charango: https://en.wikipedia.org/wiki/Charango
`Gary Wilson`_
Gary starting contributing patches to Django in 2006 while developing Web
applications for `The University of Texas`_ (UT). Since, he has made
contributions to the email and forms systems, as well as many other
improvements and code cleanups throughout the code base.
Gary lives in Austin, Texas, USA.
.. _Gary Wilson: http://thegarywilson.com/
.. _The University of Texas: https://www.utexas.edu/
`Brian Rosner`_
Brian enjoys learning more about programming languages and system
architectures and contributing to open source projects.
He helped immensely in getting Django's "newforms-admin" branch finished
in time for Django 1.0.
Brian lives in Denver, Colorado, USA.
.. _brian rosner: http://brosner.com/
`James Tauber`_
James is the lead developer of Pinax_ and the CEO and founder of
Eldarion_. He has been doing open source software since 1993, Python
since 1998 and Django since 2006. He serves on the board of the Python
Software Foundation and is currently on a leave of absence from a PhD in
linguistics.
James currently lives in Boston, MA, USA but originally hails from
Perth, Western Australia where he attended the same high school as
Russell Keith-Magee.
.. _James Tauber: http://jtauber.com/
.. _eldarion: http://eldarion.com/
.. _pinax: http://pinaxproject.com/
---
### 大一小学期 Week 3 Python Exam 2016 Docs Intro Contributing (`大一小学期/Week_3-Python/exam/2016/docs/intro/contributing.txt`)
===================================
Writing your first patch for Django
===================================
Introduction
============
Interested in giving back to the community a little? Maybe you've found a bug
in Django that you'd like to see fixed, or maybe there's a small feature you
want added.
Contributing back to Django itself is the best way to see your own concerns
addressed. This may seem daunting at first, but it's really pretty simple.
We'll walk you through the entire process, so you can learn by example.
Who's this tutorial for?
------------------------
.. seealso::
If you are looking for a reference on how to submit patches, see the
:doc:`/internals/contributing/writing-code/submitting-patches`
documentation.
For this tutorial, we expect that you have at least a basic understanding of
how Django works. This means you should be comfortable going through the
existing tutorials on :doc:`writing your first Django app`.
In addition, you should have a good understanding of Python itself. But if you
don't, `Dive Into Python`__ is a fantastic (and free) online book for
beginning Python programmers.
Those of you who are unfamiliar with version control systems and Trac will find
that this tutorial and its links include just enough information to get started.
However, you'll probably want to read some more about these different tools if
you plan on contributing to Django regularly.
For the most part though, this tutorial tries to explain as much as possible,
so that it can be of use to the widest audience.
.. admonition:: Where to get help:
If you're having trouble going through this tutorial, please post a message
to |django-developers| or drop by `#django-dev on irc.freenode.net`__ to
chat with other Django users who might be able to help.
__ http://www.diveintopython3.net/
__ irc://irc.freenode.net/django-dev
What does this tutorial cover?
------------------------------
We'll be walking you through contributing a patch to Django for the first time.
By the end of this tutorial, you should have a basic understanding of both the
tools and the processes involved. Specifically, we'll be covering the following:
* Installing Git.
* How to download a development copy of Django.
* Running Django's test suite.
* Writing a test for your patch.
* Writing the code for your patch.
* Testing your patch.
* Generating a patch file for your changes.
* Where to look for more information.
Once you're done with the tutorial, you can look through the rest of
:doc:`Django's documentation on contributing`.
It contains lots of great information and is a must read for anyone who'd like
to become a regular contributor to Django. If you've got questions, it's
probably got the answers.
.. admonition:: Python 3 required!
This tutorial assumes you are using Python 3. Get the latest version at
`Python's download page <https://www.python.org/download/>`_ or with your
operating system's package manager.
.. admonition:: For Windows users
When installing Python on Windows, make sure you check the option "Add
python.exe to Path", so that it is always available on the command line.
Code of Conduct
===============
As a contributor, you can help us keep the Django community open and inclusive.
Please read and follow our `Code of Conduct <https://www.djangoproject.com/conduct/>`_.
Installing Git
==============
For this tutorial, you'll need Git installed to download the current
development version of Django and to generate patch files for the changes you
make.
To check whether or not you have Git installed, enter ``git`` into the command
line. If you get messages saying that this command could not be found, you'll
have to download and install it, see `Git's download page`__.
.. admonition:: For Windows users
When installing Git on Windows, it is recommended that you pick the
"Git Bash" option so that Git runs in its own shell. This tutorial assumes
that's how you have installed it.
If you're not that familiar with Git, you can always find out more about its
commands (once it's installed) by typing ``git help`` into the command line.
__ http://git-scm.com/download
Getting a copy of Django's development version
==============================================
The first step to contributing to Django is to get a copy of the source code.
From the command line, use the ``cd`` command to navigate to the directory
where you'll want your local copy of Django to live.
Download the Django source code repository using the following command:
.. code-block:: console
$ git clone https://github.com/django/django.git
Now that you have a local copy of Django, you can install it just like you would
install any package using ``pip``. The most convenient way to do so is by using
a *virtual environment* (or virtualenv) which is a feature built into Python
that allows you to keep a separate directory of installed packages for each of
your projects so that they don't interfere with each other.
It's a good idea to keep all your virtualenvs in one place, for example in
``.virtualenvs/`` in your home directory. Create it if it doesn't exist yet:
.. code-block:: console
$ mkdir ~/.virtualenvs
Now create a new virtualenv by running:
.. code-block:: console
$ python3 -m venv ~/.virtualenvs/djangodev
The path is where the new environment will be saved on your computer.
.. admonition:: For Windows users
Using the built-in ``venv`` module will not work if you are also using the
Git Bash shell on Windows, since activation scripts are only created for the
system shell (``.bat``) and PowerShell (``.ps1``). Use the ``virtualenv``
package instead:
.. code-block:: none
$ pip install virtualenv
$ virtualenv ~/.virtualenvs/djangodev
.. admonition:: For Ubuntu users
On some versions of Ubuntu the above command might fail. Use the
``virtualenv`` package instead, first making sure you have ``pip3``:
.. code-block:: console
$ sudo apt-get install python3-pip
$ # Prefix the next command with sudo if it gives a permission denied error
$ pip3 install virtualenv
$ virtualenv --python=`which python3` ~/.virtualenvs/djangodev
The final step in setting up your virtualenv is to activate it:
.. code-block:: console
$ source ~/.virtualenvs/djangodev/bin/activate
If the ``source`` command is not available, you can try using a dot instead:
.. code-block:: console
$ . ~/.virtualenvs/djangodev/bin/activate
.. admonition:: For Windows users
To activate your virtualenv on Windows, run:
.. code-block:: none
$ source ~/virtualenvs/djangodev/Scripts/activate
You have to activate the virtualenv whenever you open a new terminal window.
virtualenvwrapper__ is a useful tool for making this more convenient.
__ https://virtualenvwrapper.readthedocs.io/en/latest/
Anything you install through ``pip`` from now on will be installed in your new
virtualenv, isolated from other environments and system-wide packages. Also, the
name of the currently activated virtualenv is displayed on the command line to
help you keep track of which one you are using. Go ahead and install the
previously cloned copy of Django:
.. code-block:: console
$ pip install -e /path/to/your/local/clone/django/
The installed version of Django is now pointing at your local copy. You will
immediately see any changes you make to it, which is of great help when writing
your first patch.
Rolling back to a previous revision of Django
=============================================
For this tutorial, we'll be using ticket :ticket:`24788` as a case study, so
we'll rewind Django's version history in git to before that ticket's patch was
applied. This will allow us to go through all of the steps involved in writing
that patch from scratch, including running Django's test suite.
**Keep in mind that while we'll be using an older revision of Django's trunk
for the purposes of the tutorial below, you should always use the current
development revision of Django when working on your own patch for a ticket!**
.. note::
The patch for this ticket was written by Paweł Marczewski, and it was
applied to Django as `commit 4df7e8483b2679fc1cba3410f08960bac6f51115`__.
Consequently, we'll be using the revision of Django just prior to that,
`commit 4ccfc4439a7add24f8db4ef3960d02ef8ae09887`__.
__ https://github.com/django/django/commit/4df7e8483b2679fc1cba3410f08960bac6f51115
__ https://github.com/django/django/commit/4ccfc4439a7add24f8db4ef3960d02ef8ae09887
Navigate into Django's root directory (that's the one that contains ``django``,
``docs``, ``tests``, ``AUTHORS``, etc.). You can then check out the older
revision of Django that we'll be using in the tutorial below:
.. code-block:: console
$ git checkout 4ccfc4439a7add24f8db4ef3960d02ef8ae09887
Running Django's test suite for the first time
==============================================
When contributing to Django it's very important that your code changes don't
introduce bugs into other areas of Django. One way to check that Django still
works after you make your changes is by running Django's test suite. If all
the tests still pass, then you can be reasonably sure that your changes
haven't completely broken Django. If you've never run Django's test suite
before, it's a good idea to run it once beforehand just to get familiar with
what its output is supposed to look like.
Before running the test suite, install its dependencies by first ``cd``-ing
into the Django ``tests/`` directory and then running:
.. code-block:: console
$ pip install -r requirements/py3.txt
If you encounter an error during the installation, your system might be missing
a dependency for one or more of the Python packages. Consult the failing
package's documentation or search the Web with the error message that you
encounter.
Now we are ready to run the test suite. If you're using GNU/Linux, Mac OS X or
some other flavor of Unix, run:
.. code-block:: console
$ ./runtests.py
Now sit back and relax. Django's entire test suite has over 9,600 different
tests, so it can take anywhere from 5 to 15 minutes to run, depending on the
speed of your computer.
While Django's test suite is running, you'll see a stream of characters
representing the status of each test as it's run. ``E`` indicates that an error
was raised during a test, and ``F`` indicates that a test's assertions failed.
Both of these are considered to be test failures. Meanwhile, ``x`` and ``s``
indicated expected failures and skipped tests, respectively. Dots indicate
passing tests.
Skipped tests are typically due to missing external libraries required to run
the test; see :ref:`running-unit-tests-dependencies` for a list of dependencies
and be sure to install any for tests related to the changes you are making (we
won't need any for this tutorial). Some tests are specific to a particular
database backend and will be skipped if not testing with that backend. SQLite
is the database backend for the default settings. To run the tests using a
different backend, see :ref:`running-unit-tests-settings`.
Once the tests complete, you should be greeted with a message informing you
whether the test suite passed or failed. Since you haven't yet made any changes
to Django's code, the entire test suite **should** pass. If you get failures or
errors make sure you've followed all of the previous steps properly. See
:ref:`running-unit-tests` for more information. If you're using Python 3.5+,
there will be a couple failures related to deprecation warnings that you can
ignore. These failures have since been fixed in Django.
Note that the latest Django trunk may not always be stable. When developing
against trunk, you can check `Django's continuous integration builds`__ to
determine if the failures are specific to your machine or if they are also
present in Django's official builds. If you click to view a particular build,
you can view the "Configuration Matrix" which shows failures broken down by
Python version and database backend.
__ http://djangoci.com
.. note::
For this tutorial and the ticket we're working on, testing against SQLite
is sufficient, however, it's possible (and sometimes necessary) to
:ref:`run the tests using a different database
<running-unit-tests-settings>`.
Writing some tests for your ticket
==================================
In most cases, for a patch to be accepted into Django it has to include tests.
For bug fix patches, this means writing a regression test to ensure that the
bug is never reintroduced into Django later on. A regression test should be
written in such a way that it will fail while the bug still exists and pass
once the bug has been fixed. For patches containing new features, you'll need
to include tests which ensure that the new features are working correctly.
They too should fail when the new feature is not present, and then pass once it
has been implemented.
A good way to do this is to write your new tests first, before making any
changes to the code. This style of development is called
`test-driven development`__ and can be applied to both entire projects and
single patches. After writing your tests, you then run them to make sure that
they do indeed fail (since you haven't fixed that bug or added that feature
yet). If your new tests don't fail, you'll need to fix them so that they do.
After all, a regression test that passes regardless of whether a bug is present
is not very helpful at preventing that bug from reoccurring down the road.
Now for our hands-on example.
__ https://en.wikipedia.org/wiki/Test-driven_development
Writing some tests for ticket #24788
------------------------------------
Ticket :ticket:`24788` proposes a small feature addition: the ability to
specify the class level attribute ``prefix`` on Form classes, so that::
[…] forms which ship with apps could effectively namespace themselves such
that N overlapping form fields could be POSTed at once and resolved to the
correct form.
In order to resolve this ticket, we'll add a ``prefix`` attribute to the
``BaseForm`` class. When creating instances of this class, passing a prefix to
the ``__init__()`` method will still set that prefix on the created instance.
But not passing a prefix (or passing ``None``) will use the class-level prefix.
Before we make those changes though, we're going to write a couple tests to
verify that our modification functions correctly and continues to function
correctly in the future.
Navigate to Django's ``tests/forms_tests/tests/`` folder and open the
``test_forms.py`` file. Add the following code on line 1674 right before the
``test_forms_with_null_boolean`` function::
def test_class_prefix(self):
# Prefix can be also specified at the class level.
class Person(Form):
first_name = CharField()
prefix = 'foo'
p = Person()
self.assertEqual(p.prefix, 'foo')
p = Person(prefix='bar')
self.assertEqual(p.prefix, 'bar')
This new test checks that setting a class level prefix works as expected, and
that passing a ``prefix`` parameter when creating an instance still works too.
.. admonition:: But this testing thing looks kinda hard...
If you've never had to deal with tests before, they can look a little hard
to write at first glance. Fortunately, testing is a *very* big subject in
computer programming, so there's lots of information out there:
* A good first look at writing tests for Django can be found in the
documentation on :doc:`/topics/testing/overview`.
* Dive Into Python (a free online book for beginning Python developers)
includes a great `introduction to Unit Testing`__.
* After reading those, if you want something a little meatier to sink
your teeth into, there's always the Python :mod:`unittest` documentation.
__ http://www.diveintopython.net/unit_testing/index.html
Running your new test
---------------------
Remember that we haven't actually made any modifications to ``BaseForm`` yet,
so our tests are going to fail. Let's run all the tests in the ``forms_tests``
folder to make sure that's really what happens. From the command line, ``cd``
into the Django ``tests/`` directory and run:
.. code-block:: console
$ ./runtests.py forms_tests
If the tests ran correctly, you should see one failure corresponding to the test
method we added. If all of the tests passed, then you'll want to make sure that
you added the new test shown above to the appropriate folder and class.
Writing the code for your ticket
================================
Next we'll be adding the functionality described in ticket :ticket:`24788` to
Django.
Writing the code for ticket #24788
----------------------------------
Navigate to the ``django/django/forms/`` folder and open the ``forms.py`` file.
Find the ``BaseForm`` class on line 72 and add the ``prefix`` class attribute
right after the ``field_order`` attribute::
class BaseForm(object):
# This is the main implementation of all the Form logic. Note that this
# class is different than Form. See the comments by the Form class for
# more information. Any improvements to the form API should be made to
# *this* class, not to the Form class.
field_order = None
prefix = None
Verifying your test now passes
------------------------------
Once you're done modifying Django, we need to make sure that the tests we wrote
earlier pass, so we can see whether the code we wrote above is working
correctly. To run the tests in the ``forms_tests`` folder, ``cd`` into the
Django ``tests/`` directory and run:
.. code-block:: console
$ ./runtests.py forms_tests
Oops, good thing we wrote those tests! You should still see one failure with
the following exception::
AssertionError: None != 'foo'
We forgot to add the conditional statement in the ``__init__`` method. Go ahead
and change ``self.prefix = prefix`` that is now on line 87 of
``django/forms/forms.py``, adding a conditional statement::
if prefix is not None:
self.prefix = prefix
Re-run the tests and everything should pass. If it doesn't, make sure you
correctly modified the ``BaseForm`` class as shown above and copied the new test
correctly.
Running Django's test suite for the second time
===============================================
Once you've verified that your patch and your test are working correctly, it's
a good idea to run the entire Django test suite just to verify that your change
hasn't introduced any bugs into other areas of Django. While successfully
passing the entire test suite doesn't guarantee your code is bug free, it does
help identify many bugs and regressions that might otherwise go unnoticed.
To run the entire Django test suite, ``cd`` into the Django ``tests/``
directory and run:
.. code-block:: console
$ ./runtests.py
As long as you don't see any failures, you're good to go.
Writing Documentation
=====================
This is a new feature, so it should be documented. Add the following section on
line 1068 (at the end of the file) of ``django/docs/ref/forms/api.txt``::
The prefix can also be specified on the form class::
>>> class PersonForm(forms.Form):
... ...
... prefix = 'person'
.. versionadded:: 1.9
The ability to specify ``prefix`` on the form class was added.
Since this new feature will be in an upcoming release it is also added to the
release notes for Django 1.9, on line 164 under the "Forms" section in the file
``docs/releases/1.9.txt``::
* A form prefix can be specified inside a form class, not only when
instantiating a form. See :ref:`form-prefix` for details.
For more information on writing documentation, including an explanation of what
the ``versionadded`` bit is all about, see
:doc:`/internals/contributing/writing-documentation`. That page also includes
an explanation of how to build a copy of the documentation locally, so you can
preview the HTML that will be generated.
Generating a patch for your changes
===================================
Now it's time to generate a patch file that can be uploaded to Trac or applied
to another copy of Django. To get a look at the content of your patch, run the
following command:
.. code-block:: console
$ git diff
This will display the differences between your current copy of Django (with
your changes) and the revision that you initially checked out earlier in the
tutorial.
Once you're done looking at the patch, hit the ``q`` key to exit back to the
command line. If the patch's content looked okay, you can run the following
command to save the patch file to your current working directory:
.. code-block:: console
$ git diff > 24788.diff
You should now have a file in the root Django directory called ``24788.diff``.
This patch file contains all your changes and should look this:
.. code-block:: diff
diff --git a/django/forms/forms.py b/django/forms/forms.py
index 509709f..d1370de 100644
--- a/django/forms/forms.py
+++ b/django/forms/forms.py
@@ -75,6 +75,7 @@ class BaseForm(object):
# information. Any improvements to the form API should be made to *this*
# class, not to the Form class.
field_order = None
+ prefix = None
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=None,
@@ -83,7 +84,8 @@ class BaseForm(object):
self.data = data or {}
self.files = files or {}
self.auto_id = auto_id
- self.prefix = prefix
+ if prefix is not None:
+ self.prefix = prefix
self.initial = initial or {}
self.error_class = error_class
# Translators: This is the default suffix added to form field labels
diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt
index 3bc39cd..008170d 100644
--- a/docs/ref/forms/api.txt
+++ b/docs/ref/forms/api.txt
@@ -1065,3 +1065,13 @@ You can put several Django forms inside one ``<form>`` tag. To give each
>>> print(father.as_ul())
<li><label for="id_father-first_name">First name:</label> </li>
<li><label for="id_father-last_name">Last name:</label> </li>
+
+The prefix can also be specified on the form class::
+
+ >>> class PersonForm(forms.Form):
+ ... ...
+ ... prefix = 'person'
+
+.. versionadded:: 1.9
+
+ The ability to specify ``prefix`` on the form class was added.
diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt
index 5b58f79..f9bb9de 100644
--- a/docs/releases/1.9.txt
+++ b/docs/releases/1.9.txt
@@ -161,6 +161,9 @@ Forms
:attr:`~django.forms.Form.field_order` attribute, the ``field_order``
constructor argument , or the :meth:`~django.forms.Form.order_fields` method.
+* A form prefix can be specified inside a form class, not only when
+ instantiating a form. See :ref:`form-prefix` for details.
+
Generic Views
^^^^^^^^^^^^^
diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py
index 690f205..e07fae2 100644
--- a/tests/forms_tests/tests/test_forms.py
+++ b/tests/forms_tests/tests/test_forms.py
@@ -1671,6 +1671,18 @@ class FormsTestCase(SimpleTestCase):
self.assertEqual(p.cleaned_data['last_name'], 'Lennon')
self.assertEqual(p.cleaned_data['birthday'], datetime.date(1940, 10, 9))
+ def test_class_prefix(self):
+ # Prefix can be also specified at the class level.
+ class Person(Form):
+ first_name = CharField()
+ prefix = 'foo'
+
+ p = Person()
+ self.assertEqual(p.prefix, 'foo')
+
+ p = Person(prefix='bar')
+ self.assertEqual(p.prefix, 'bar')
+
def test_forms_with_null_boolean(self):
# NullBooleanField is a bit of a special case because its presentation (widget)
# is different than its data. This is handled transparently, though.
So what do I do next?
=====================
Congratulations, you've generated your very first Django patch! Now that you've
got that under your belt, you can put those skills to good use by helping to
improve Django's codebase. Generating patches and attaching them to Trac
tickets is useful, however, since we are using git - adopting a more :doc:`git
oriented workflow ` is
recommended.
Since we never committed our changes locally, perform the following to get your
git branch back to a good starting point:
.. code-block:: console
$ git reset --hard HEAD
$ git checkout master
More information for new contributors
-------------------------------------
Before you get too into writing patches for Django, there's a little more
information on contributing that you should probably take a look at:
* You should make sure to read Django's documentation on
:doc:`claiming tickets and submitting patches
`.
It covers Trac etiquette, how to claim tickets for yourself, expected
coding style for patches, and many other important details.
* First time contributors should also read Django's :doc:`documentation
for first time contributors`.
It has lots of good advice for those of us who are new to helping out
with Django.
* After those, if you're still hungry for more information about
contributing, you can always browse through the rest of
:doc:`Django's documentation on contributing`.
It contains a ton of useful information and should be your first source
for answering any questions you might have.
Finding your first real ticket
------------------------------
Once you've looked through some of that information, you'll be ready to go out
and find a ticket of your own to write a patch for. Pay special attention to
tickets with the "easy pickings" criterion. These tickets are often much
simpler in nature and are great for first time contributors. Once you're
familiar with contributing to Django, you can move on to writing patches for
more difficult and complicated tickets.
If you just want to get started already (and nobody would blame you!), try
taking a look at the list of `easy tickets that need patches`__ and the
`easy tickets that have patches which need improvement`__. If you're familiar
with writing tests, you can also look at the list of
`easy tickets that need tests`__. Just remember to follow the guidelines about
claiming tickets that were mentioned in the link to Django's documentation on
:doc:`claiming tickets and submitting patches
`.
__ https://code.djangoproject.com/query?status=new&status=reopened&has_patch=0&easy=1&col=id&col=summary&col=status&col=owner&col=type&col=milestone&order=priority
__ https://code.djangoproject.com/query?status=new&status=reopened&needs_better_patch=1&easy=1&col=id&col=summary&col=status&col=owner&col=type&col=milestone&order=priority
__ https://code.djangoproject.com/query?status=new&status=reopened&needs_tests=1&easy=1&col=id&col=summary&col=status&col=owner&col=type&col=milestone&order=priority
What's next?
------------
After a ticket has a patch, it needs to be reviewed by a second set of eyes.
After uploading a patch or submitting a pull request, be sure to update the
ticket metadata by setting the flags on the ticket to say "has patch",
"doesn't need tests", etc, so others can find it for review. Contributing
doesn't necessarily always mean writing a patch from scratch. Reviewing
existing patches is also a very helpful contribution. See
:doc:`/internals/contributing/triaging-tickets` for details.
---
### 大一小学期 Week 3 Python Exam 2016 Docs Intro Index (`大一小学期/Week_3-Python/exam/2016/docs/intro/index.txt`)
===============
Getting started
===============
New to Django? Or to Web development in general? Well, you came to the right
place: read this material to quickly get up and running.
.. toctree::
:maxdepth: 1
overview
install
tutorial01
tutorial02
tutorial03
tutorial04
tutorial05
tutorial06
tutorial07
reusable-apps
whatsnext
contributing
.. seealso::
If you're new to Python_, you might want to start by getting an idea of what
the language is like. Django is 100% Python, so if you've got minimal
comfort with Python you'll probably get a lot more out of Django.
If you're new to programming entirely, you might want to start with this
`list of Python resources for non-programmers`_
If you already know a few other languages and want to get up to speed with
Python quickly, we recommend `Dive Into Python`_. If that's not quite your
style, there are many other `books about Python`_.
.. _python: https://python.org/
.. _list of Python resources for non-programmers: https://wiki.python.org/moin/BeginnersGuide/NonProgrammers
.. _Dive Into Python: http://www.diveintopython3.net/
.. _books about Python: https://wiki.python.org/moin/PythonBooks
---
### 大一小学期 Week 3 Python Exam 2016 Docs Intro Install (`大一小学期/Week_3-Python/exam/2016/docs/intro/install.txt`)
===================
Quick install guide
===================
Before you can use Django, you'll need to get it installed. We have a
:doc:`complete installation guide </topics/install>` that covers all the
possibilities; this guide will guide you to a simple, minimal installation
that'll work while you walk through the introduction.
Install Python
==============
Being a Python Web framework, Django requires Python. See
:ref:`faq-python-version-support` for details. Python includes a lightweight
database called SQLite_ so you won't need to set up a database just yet.
.. _sqlite: https://sqlite.org/
Get the latest version of Python at https://www.python.org/download/ or with
your operating system's package manager.
.. admonition:: Django on Jython
If you use Jython_ (a Python implementation for the Java platform), you'll
need to follow a few additional steps. See :doc:`/howto/jython` for details.
.. _jython: http://www.jython.org/
You can verify that Python is installed by typing ``python`` from your shell;
you should see something like::
Python 3.4.x
[GCC 4.x] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
Set up a database
=================
This step is only necessary if you'd like to work with a "large" database engine
like PostgreSQL, MySQL, or Oracle. To install such a database, consult the
:ref:`database installation information <database-installation>`.
Remove any old versions of Django
=================================
If you are upgrading your installation of Django from a previous version, you
will need to :ref:`uninstall the old Django version before installing the new
version <removing-old-versions-of-django>`.
Install Django
==============
You've got three easy options to install Django:
* Install a version of Django :doc:`provided by your operating system
distribution </misc/distributions>`. This is the quickest option for those
who have operating systems that distribute Django.
* :ref:`Install an official release `. This
is the best approach for most users.
* :ref:`Install the latest development version
`. This option is for enthusiasts who want
the latest-and-greatest features and aren't afraid of running brand new code.
You might encounter new bugs in the development version, but reporting them
helps the development of Django. Also, releases of third-party packages are
less likely to be compatible with the development version than with the
latest stable release.
.. admonition:: Always refer to the documentation that corresponds to the
version of Django you're using!
If you do either of the first two steps, keep an eye out for parts of the
documentation marked **new in development version**. That phrase flags
features that are only available in development versions of Django, and
they likely won't work with an official release.
Verifying
=========
To verify that Django can be seen by Python, type ``python`` from your shell.
Then at the Python prompt, try to import Django:
.. parsed-literal::
>>> import django
>>> print(django.get_version())
|version|
You may have another version of Django installed.
That's it!
==========
That's it -- you can now :doc:`move onto the tutorial `.
---
### 大一小学期 Week 3 Python Exam 2016 Docs Intro Overview (`大一小学期/Week_3-Python/exam/2016/docs/intro/overview.txt`)
==================
Django at a glance
==================
Because Django was developed in a fast-paced newsroom environment, it was
designed to make common Web-development tasks fast and easy. Here's an informal
overview of how to write a database-driven Web app with Django.
The goal of this document is to give you enough technical specifics to
understand how Django works, but this isn't intended to be a tutorial or
reference -- but we've got both! When you're ready to start a project, you can
:doc:`start with the tutorial ` or :doc:`dive right into more
detailed documentation </topics/index>`.
Design your model
=================
Although you can use Django without a database, it comes with an
`object-relational mapper`_ in which you describe your database layout in Python
code.
.. _object-relational mapper: https://en.wikipedia.org/wiki/Object-relational_mapping
The :doc:`data-model syntax </topics/db/models>` offers many rich ways of
representing your models -- so far, it's been solving many years' worth of
database-schema problems. Here's a quick example:
.. snippet::
:filename: mysite/news/models.py
from django.db import models
class Reporter(models.Model):
full_name = models.CharField(max_length=70)
def __str__(self): # __unicode__ on Python 2
return self.full_name
class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
def __str__(self): # __unicode__ on Python 2
return self.headline
Install it
==========
Next, run the Django command-line utility to create the database tables
automatically:
.. code-block:: console
$ python manage.py migrate
The :djadmin:`migrate` command looks at all your available models and creates
tables in your database for whichever tables don't already exist, as well as
optionally providing :doc:`much richer schema control </topics/migrations>`.
Enjoy the free API
==================
With that, you've got a free, and rich, :doc:`Python API </topics/db/queries>`
to access your data. The API is created on the fly, no code generation
necessary:
.. code-block:: python
# Import the models we created from our "news" app
>>> from news.models import Reporter, Article
# No reporters are in the system yet.
>>> Reporter.objects.all()
<QuerySet []>
# Create a new Reporter.
>>> r = Reporter(full_name='John Smith')
# Save the object into the database. You have to call save() explicitly.
>>> r.save()
# Now it has an ID.
>>> r.id
1
# Now the new reporter is in the database.
>>> Reporter.objects.all()
<QuerySet [<Reporter: John Smith>]>
# Fields are represented as attributes on the Python object.
>>> r.full_name
'John Smith'
# Django provides a rich database lookup API.
>>> Reporter.objects.get(id=1)
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__startswith='John')
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__contains='mith')
<Reporter: John Smith>
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Reporter matching query does not exist.
# Create an article.
>>> from datetime import date
>>> a = Article(pub_date=date.today(), headline='Django is cool',
... content='Yeah.', reporter=r)
>>> a.save()
# Now the article is in the database.
>>> Article.objects.all()
<QuerySet [<Article: Django is cool>]>
# Article objects get API access to related Reporter objects.
>>> r = a.reporter
>>> r.full_name
'John Smith'
# And vice versa: Reporter objects get API access to Article objects.
>>> r.article_set.all()
<QuerySet [<Article: Django is cool>]>
# The API follows relationships as far as you need, performing efficient
# JOINs for you behind the scenes.
# This finds all articles by a reporter whose name starts with "John".
>>> Article.objects.filter(reporter__full_name__startswith='John')
<QuerySet [<Article: Django is cool>]>
# Change an object by altering its attributes and calling save().
>>> r.full_name = 'Billy Goat'
>>> r.save()
# Delete an object with delete().
>>> r.delete()
A dynamic admin interface: it's not just scaffolding -- it's the whole house
============================================================================
Once your models are defined, Django can automatically create a professional,
production ready :doc:`administrative interface </ref/contrib/admin/index>` --
a website that lets authenticated users add, change and delete objects. It's
as easy as registering your model in the admin site:
.. snippet::
:filename: mysite/news/models.py
from django.db import models
class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
.. snippet::
:filename: mysite/news/admin.py
from django.contrib import admin
from . import models
admin.site.register(models.Article)
The philosophy here is that your site is edited by a staff, or a client, or
maybe just you -- and you don't want to have to deal with creating backend
interfaces just to manage content.
One typical workflow in creating Django apps is to create models and get the
admin sites up and running as fast as possible, so your staff (or clients) can
start populating data. Then, develop the way data is presented to the public.
Design your URLs
================
A clean, elegant URL scheme is an important detail in a high-quality Web
application. Django encourages beautiful URL design and doesn't put any cruft
in URLs, like ``.php`` or ``.asp``.
To design URLs for an app, you create a Python module called a :doc:`URLconf
</topics/http/urls>`. A table of contents for your app, it contains a simple
mapping between URL patterns and Python callback functions. URLconfs also serve
to decouple URLs from Python code.
Here's what a URLconf might look like for the ``Reporter``/``Article``
example above:
.. snippet::
:filename: mysite/news/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
The code above maps URLs, as simple :ref:`regular expressions <regex-howto>`,
to the location of Python callback functions ("views"). The regular expressions
use parenthesis to "capture" values from the URLs. When a user requests a page,
Django runs through each pattern, in order, and stops at the first one that
matches the requested URL. (If none of them matches, Django calls a
special-case 404 view.) This is blazingly fast, because the regular expressions
are compiled at load time.
Once one of the regexes matches, Django imports and calls the given view, which
is a simple Python function. Each view gets passed a request object --
which contains request metadata -- and the values captured in the regex.
For example, if a user requested the URL "/articles/2005/05/39323/", Django
would call the function ``news.views.article_detail(request,
'2005', '05', '39323')``.
Write your views
================
Each view is responsible for doing one of two things: Returning an
:class:`~django.http.HttpResponse` object containing the content for the
requested page, or raising an exception such as :class:`~django.http.Http404`.
The rest is up to you.
Generally, a view retrieves data according to the parameters, loads a template
and renders the template with the retrieved data. Here's an example view for
``year_archive`` from above:
.. snippet::
:filename: mysite/news/views.py
from django.shortcuts import render
from .models import Article
def year_archive(request, year):
a_list = Article.objects.filter(pub_date__year=year)
context = {'year': year, 'article_list': a_list}
return render(request, 'news/year_archive.html', context)
This example uses Django's :doc:`template system </topics/templates>`, which has
several powerful features but strives to stay simple enough for non-programmers
to use.
Design your templates
=====================
The code above loads the ``news/year_archive.html`` template.
Django has a template search path, which allows you to minimize redundancy among
templates. In your Django settings, you specify a list of directories to check
for templates with :setting:`DIRS <TEMPLATES-DIRS>`. If a template doesn't exist
in the first directory, it checks the second, and so on.
Let's say the ``news/year_archive.html`` template was found. Here's what that
might look like:
.. snippet:: html+django
:filename: mysite/news/templates/news/year_archive.html
{% extends "base.html" %}
{% block title %}Articles for {{ year }}{% endblock %}
{% block content %}
<h1>Articles for {{ year }}</h1>
{% for article in article_list %}
{{ article.headline }}
By {{ article.reporter.full_name }}
Published {{ article.pub_date|date:"F j, Y" }}
{% endfor %}
{% endblock %}
Variables are surrounded by double-curly braces. ``{{ article.headline }}``
means "Output the value of the article's headline attribute." But dots aren't
used only for attribute lookup. They also can do dictionary-key lookup, index
lookup and function calls.
Note ``{{ article.pub_date|date:"F j, Y" }}`` uses a Unix-style "pipe" (the "|"
character). This is called a template filter, and it's a way to filter the value
of a variable. In this case, the date filter formats a Python datetime object in
the given format (as found in PHP's date function).
You can chain together as many filters as you'd like. You can write :ref:`custom
template filters <howto-writing-custom-template-filters>`. You can write
:doc:`custom template tags </howto/custom-template-tags>`, which run custom
Python code behind the scenes.
Finally, Django uses the concept of "template inheritance". That's what the
``{% extends "base.html" %}`` does. It means "First load the template called
'base', which has defined a bunch of blocks, and fill the blocks with the
following blocks." In short, that lets you dramatically cut down on redundancy
in templates: each template has to define only what's unique to that template.
Here's what the "base.html" template, including the use of :doc:`static files
</howto/static-files/index>`, might look like:
.. snippet:: html+django
:filename: mysite/templates/base.html
{% load static %}
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
{% block content %}{% endblock %}
</html>
Simplistically, it defines the look-and-feel of the site (with the site's logo),
and provides "holes" for child templates to fill. This makes a site redesign as
easy as changing a single file -- the base template.
It also lets you create multiple versions of a site, with different base
templates, while reusing child templates. Django's creators have used this
technique to create strikingly different mobile versions of sites -- simply by
creating a new base template.
Note that you don't have to use Django's template system if you prefer another
system. While Django's template system is particularly well-integrated with
Django's model layer, nothing forces you to use it. For that matter, you don't
have to use Django's database API, either. You can use another database
abstraction layer, you can read XML files, you can read files off disk, or
anything you want. Each piece of Django -- models, views, templates -- is
decoupled from the next.
This is just the surface
========================
This has been only a quick overview of Django's functionality. Some more useful
features:
* A :doc:`caching framework </topics/cache>` that integrates with memcached
or other backends.
* A :doc:`syndication framework </ref/contrib/syndication>` that makes
creating RSS and Atom feeds as easy as writing a small Python class.
* More sexy automatically-generated admin features -- this overview barely
scratched the surface.
The next obvious steps are for you to `download Django`_, read :doc:`the
tutorial ` and join `the community`_. Thanks for your
interest!
.. _download Django: https://www.djangoproject.com/download/
.. _the community: https://www.djangoproject.com/community/
---
### 大一小学期 Week 3 Python Exam 2016 Docs Intro Reusable Apps (`大一小学期/Week_3-Python/exam/2016/docs/intro/reusable-apps.txt`)
=============================================
Advanced tutorial: How to write reusable apps
=============================================
This advanced tutorial begins where :doc:`Tutorial 7 `
left off. We'll be turning our Web-poll into a standalone Python package
you can reuse in new projects and share with other people.
If you haven't recently completed Tutorials 1–7, we encourage you to review
these so that your example project matches the one described below.
Reusability matters
===================
It's a lot of work to design, build, test and maintain a web application. Many
Python and Django projects share common problems. Wouldn't it be great if we
could save some of this repeated work?
Reusability is the way of life in Python. `The Python Package Index (PyPI)
<https://pypi.python.org/pypi>`_ has a vast range of packages you can use in
your own Python programs. Check out `Django Packages
<https://www.djangopackages.com>`_ for existing reusable apps you could
incorporate in your project. Django itself is also just a Python package. This
means that you can take existing Python packages or Django apps and compose
them into your own web project. You only need to write the parts that make
your project unique.
Let's say you were starting a new project that needed a polls app like the one
we've been working on. How do you make this app reusable? Luckily, you're well
on the way already. In :doc:`Tutorial 3 `, we saw how we
could decouple polls from the project-level URLconf using an ``include``.
In this tutorial, we'll take further steps to make the app easy to use in new
projects and ready to publish for others to install and use.
.. admonition:: Package? App?
A Python :term:`package` provides a way of grouping related Python code for
easy reuse. A package contains one or more files of Python code (also known
as "modules").
A package can be imported with ``import foo.bar`` or ``from foo import
bar``. For a directory (like ``polls``) to form a package, it must contain
a special file ``__init__.py``, even if this file is empty.
A Django *application* is just a Python package that is specifically
intended for use in a Django project. An application may use common Django
conventions, such as having ``models``, ``tests``, ``urls``, and ``views``
submodules.
Later on we use the term *packaging* to describe the process of making a
Python package easy for others to install. It can be a little confusing, we
know.
Your project and your reusable app
==================================
After the previous tutorials, our project should look like this::
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
polls/
__init__.py
admin.py
migrations/
__init__.py
0001_initial.py
models.py
static/
polls/
images/
background.gif
style.css
templates/
polls/
detail.html
index.html
results.html
tests.py
urls.py
views.py
templates/
admin/
base_site.html
You created ``mysite/templates`` in :doc:`Tutorial 7 `,
and ``polls/templates`` in :doc:`Tutorial 3 `. Now perhaps
it is clearer why we chose to have separate template directories for the
project and application: everything that is part of the polls application is in
``polls``. It makes the application self-contained and easier to drop into a
new project.
The ``polls`` directory could now be copied into a new Django project and
immediately reused. It's not quite ready to be published though. For that, we
need to package the app to make it easy for others to install.
.. _installing-reusable-apps-prerequisites:
Installing some prerequisites
=============================
The current state of Python packaging is a bit muddled with various tools. For
this tutorial, we're going to use setuptools_ to build our package. It's the
recommended packaging tool (merged with the ``distribute`` fork). We'll also be
using `pip`_ to install and uninstall it. You should install these
two packages now. If you need help, you can refer to :ref:`how to install
Django with pip`. You can install ``setuptools``
the same way.
.. _setuptools: https://pypi.python.org/pypi/setuptools
.. _pip: https://pypi.python.org/pypi/pip
Packaging your app
==================
Python *packaging* refers to preparing your app in a specific format that can
be easily installed and used. Django itself is packaged very much like
this. For a small app like polls, this process isn't too difficult.
1. First, create a parent directory for ``polls``, outside of your Django
project. Call this directory ``django-polls``.
.. admonition:: Choosing a name for your app
When choosing a name for your package, check resources like PyPI to avoid
naming conflicts with existing packages. It's often useful to prepend
``django-`` to your module name when creating a package to distribute.
This helps others looking for Django apps identify your app as Django
specific.
Application labels (that is, the final part of the dotted path to
application packages) *must* be unique in :setting:`INSTALLED_APPS`.
Avoid using the same label as any of the Django :doc:`contrib packages
</ref/contrib/index>`, for example ``auth``, ``admin``, or
``messages``.
2. Move the ``polls`` directory into the ``django-polls`` directory.
3. Create a file ``django-polls/README.rst`` with the following contents:
.. snippet::
:filename: django-polls/README.rst
=====
Polls
=====
Polls is a simple Django app to conduct Web-based polls. For each
question, visitors can choose between a fixed number of answers.
Detailed documentation is in the "docs" directory.
Quick start
-----------
1. Add "polls" to your INSTALLED_APPS setting like this::
INSTALLED_APPS = [
...
'polls',
]
2. Include the polls URLconf in your project urls.py like this::
url(r'^polls/', include('polls.urls')),
3. Run `python manage.py migrate` to create the polls models.
4. Start the development server and visit http://127.0.0.1:8000/admin/
to create a poll (you'll need the Admin app enabled).
5. Visit http://127.0.0.1:8000/polls/ to participate in the poll.
4. Create a ``django-polls/LICENSE`` file. Choosing a license is beyond the
scope of this tutorial, but suffice it to say that code released publicly
without a license is *useless*. Django and many Django-compatible apps are
distributed under the BSD license; however, you're free to pick your own
license. Just be aware that your licensing choice will affect who is able
to use your code.
5. Next we'll create a ``setup.py`` file which provides details about how to
build and install the app. A full explanation of this file is beyond the
scope of this tutorial, but the `setuptools docs
<https://setuptools.readthedocs.io/en/latest/>`_ have a good
explanation. Create a file ``django-polls/setup.py`` with the following
contents:
.. snippet::
:filename: django-polls/setup.py
import os
from setuptools import find_packages, setup
with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as readme:
README = readme.read()
# allow setup.py to be run from any path
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
setup(
name='django-polls',
version='0.1',
packages=find_packages(),
include_package_data=True,
license='BSD License', # example license
description='A simple Django app to conduct Web-based polls.',
long_description=README,
url='https://www.example.com/',
author='Your Name',
author_email='[email protected]',
classifiers=[
'Environment :: Web Environment',
'Framework :: Django',
'Framework :: Django :: X.Y', # replace "X.Y" as appropriate
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License', # example license
'Operating System :: OS Independent',
'Programming Language :: Python',
# Replace these appropriately if you are stuck on Python 2.
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
],
)
6. Only Python modules and packages are included in the package by default. To
include additional files, we'll need to create a ``MANIFEST.in`` file. The
setuptools docs referred to in the previous step discuss this file in more
details. To include the templates, the ``README.rst`` and our ``LICENSE``
file, create a file ``django-polls/MANIFEST.in`` with the following
contents:
.. snippet::
:filename: django-polls/MANIFEST.in
include LICENSE
include README.rst
recursive-include polls/static *
recursive-include polls/templates *
7. It's optional, but recommended, to include detailed documentation with your
app. Create an empty directory ``django-polls/docs`` for future
documentation. Add an additional line to ``django-polls/MANIFEST.in``::
recursive-include docs *
Note that the ``docs`` directory won't be included in your package unless
you add some files to it. Many Django apps also provide their documentation
online through sites like `readthedocs.org <https://readthedocs.org>`_.
8. Try building your package with ``python setup.py sdist`` (run from inside
``django-polls``). This creates a directory called ``dist`` and builds your
new package, ``django-polls-0.1.tar.gz``.
For more information on packaging, see Python's `Tutorial on Packaging and
Distributing Projects <https://packaging.python.org/en/latest/distributing.html>`_.
Using your own package
======================
Since we moved the ``polls`` directory out of the project, it's no longer
working. We'll now fix this by installing our new ``django-polls`` package.
.. admonition:: Installing as a user library
The following steps install ``django-polls`` as a user library. Per-user
installs have a lot of advantages over installing the package system-wide,
such as being usable on systems where you don't have administrator access
as well as preventing the package from affecting system services and other
users of the machine.
Note that per-user installations can still affect the behavior of system
tools that run as that user, so ``virtualenv`` is a more robust solution
(see below).
1. To install the package, use pip (you already :ref:`installed it
`, right?)::
pip install --user django-polls/dist/django-polls-0.1.tar.gz
2. With luck, your Django project should now work correctly again. Run the
server again to confirm this.
3. To uninstall the package, use pip::
pip uninstall django-polls
.. _pip: https://pypi.python.org/pypi/pip
Publishing your app
===================
Now that we've packaged and tested ``django-polls``, it's ready to share with
the world! If this wasn't just an example, you could now:
* Email the package to a friend.
* Upload the package on your website.
* Post the package on a public repository, such as `the Python Package Index
(PyPI)`_. `packaging.python.org <https://packaging.python.org>`_ has `a good
tutorial <https://packaging.python.org/en/latest/distributing.html#uploading-your-project-to-pypi>`_
for doing this.
Installing Python packages with virtualenv
==========================================
Earlier, we installed the polls app as a user library. This has some
disadvantages:
* Modifying the user libraries can affect other Python software on your system.
* You won't be able to run multiple versions of this package (or others with
the same name).
Typically, these situations only arise once you're maintaining several Django
projects. When they do, the best solution is to use `virtualenv
<http://www.virtualenv.org/>`_. This tool allows you to maintain multiple
isolated Python environments, each with its own copy of the libraries and
package namespace.
---
### 大一小学期 Week 3 Python Exam 2016 Docs Intro Tutorial01 (`大一小学期/Week_3-Python/exam/2016/docs/intro/tutorial01.txt`)
=====================================
Writing your first Django app, part 1
=====================================
Let's learn by example.
Throughout this tutorial, we'll walk you through the creation of a basic
poll application.
It'll consist of two parts:
* A public site that lets people view polls and vote in them.
* An admin site that lets you add, change, and delete polls.
We'll assume you have :doc:`Django installed ` already. You can
tell Django is installed and which version by running the following command:
.. code-block:: console
$ python -m django --version
If Django is installed, you should see the version of your installation. If it
isn't, you'll get an error telling "No module named django".
This tutorial is written for Django |version| and Python 3.4 or later. If the
Django version doesn't match, you can refer to the tutorial for your version
of Django by using the version switcher at the bottom right corner of this
page, or update Django to the newest version. If you are still using Python
2.7, you will need to adjust the code samples slightly, as described in
comments.
See :doc:`How to install Django </topics/install>` for advice on how to remove
older versions of Django and install a newer one.
.. admonition:: Where to get help:
If you're having trouble going through this tutorial, please post a message
to |django-users| or drop by `#django on irc.freenode.net
`_ to chat with other Django users who might
be able to help.
Creating a project
==================
If this is your first time using Django, you'll have to take care of some
initial setup. Namely, you'll need to auto-generate some code that establishes a
Django :term:`project` -- a collection of settings for an instance of Django,
including database configuration, Django-specific options and
application-specific settings.
From the command line, ``cd`` into a directory where you'd like to store your
code, then run the following command:
.. code-block:: console
$ django-admin startproject mysite
This will create a ``mysite`` directory in your current directory. If it didn't
work, see :ref:`troubleshooting-django-admin`.
.. note::
You'll need to avoid naming projects after built-in Python or Django
components. In particular, this means you should avoid using names like
``django`` (which will conflict with Django itself) or ``test`` (which
conflicts with a built-in Python package).
.. admonition:: Where should this code live?
If your background is in plain old PHP (with no use of modern frameworks),
you're probably used to putting code under the Web server's document root
(in a place such as ``/var/www``). With Django, you don't do that. It's
not a good idea to put any of this Python code within your Web server's
document root, because it risks the possibility that people may be able
to view your code over the Web. That's not good for security.
Put your code in some directory **outside** of the document root, such as
:file:`/home/mycode`.
Let's look at what :djadmin:`startproject` created::
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
These files are:
* The outer :file:`mysite/` root directory is just a container for your
project. Its name doesn't matter to Django; you can rename it to anything
you like.
* :file:`manage.py`: A command-line utility that lets you interact with this
Django project in various ways. You can read all the details about
:file:`manage.py` in :doc:`/ref/django-admin`.
* The inner :file:`mysite/` directory is the actual Python package for your
project. Its name is the Python package name you'll need to use to import
anything inside it (e.g. ``mysite.urls``).
* :file:`mysite/__init__.py`: An empty file that tells Python that this
directory should be considered a Python package. If you're a Python beginner,
read :ref:`more about packages <tut-packages>` in the official Python docs.
* :file:`mysite/settings.py`: Settings/configuration for this Django
project. :doc:`/topics/settings` will tell you all about how settings
work.
* :file:`mysite/urls.py`: The URL declarations for this Django project; a
"table of contents" of your Django-powered site. You can read more about
URLs in :doc:`/topics/http/urls`.
* :file:`mysite/wsgi.py`: An entry-point for WSGI-compatible web servers to
serve your project. See :doc:`/howto/deployment/wsgi/index` for more details.
The development server
======================
Let's verify your Django project works. Change into the outer :file:`mysite` directory, if
you haven't already, and run the following commands:
.. code-block:: console
$ python manage.py runserver
You'll see the following output on the command line:
.. parsed-literal::
Performing system checks...
System check identified no issues (0 silenced).
You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.
|today| - 15:50:53
Django version |version|, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
.. note::
Ignore the warning about unapplied database migrations for now; we'll deal
with the database shortly.
You've started the Django development server, a lightweight Web server written
purely in Python. We've included this with Django so you can develop things
rapidly, without having to deal with configuring a production server -- such as
Apache -- until you're ready for production.
Now's a good time to note: **don't** use this server in anything resembling a
production environment. It's intended only for use while developing. (We're in
the business of making Web frameworks, not Web servers.)
Now that the server's running, visit http://127.0.0.1:8000/ with your Web
browser. You'll see a "Welcome to Django" page, in pleasant, light-blue pastel.
It worked!
.. admonition:: Changing the port
By default, the :djadmin:`runserver` command starts the development server
on the internal IP at port 8000.
If you want to change the server's port, pass
it as a command-line argument. For instance, this command starts the server
on port 8080:
.. code-block:: console
$ python manage.py runserver 8080
If you want to change the server's IP, pass it along with the port. So to
listen on all public IPs (useful if you want to show off your work on other
computers on your network), use:
.. code-block:: console
$ python manage.py runserver 0.0.0.0:8000
Full docs for the development server can be found in the
:djadmin:`runserver` reference.
.. admonition:: Automatic reloading of :djadmin:`runserver`
The development server automatically reloads Python code for each request
as needed. You don't need to restart the server for code changes to take
effect. However, some actions like adding files don't trigger a restart,
so you'll have to restart the server in these cases.
Creating the Polls app
======================
Now that your environment -- a "project" -- is set up, you're set to start
doing work.
Each application you write in Django consists of a Python package that follows
a certain convention. Django comes with a utility that automatically generates
the basic directory structure of an app, so you can focus on writing code
rather than creating directories.
.. admonition:: Projects vs. apps
What's the difference between a project and an app? An app is a Web
application that does something -- e.g., a Weblog system, a database of
public records or a simple poll app. A project is a collection of
configuration and apps for a particular website. A project can contain
multiple apps. An app can be in multiple projects.
Your apps can live anywhere on your :ref:`Python path <tut-searchpath>`. In
this tutorial, we'll create our poll app right next to your :file:`manage.py`
file so that it can be imported as its own top-level module, rather than a
submodule of ``mysite``.
To create your app, make sure you're in the same directory as :file:`manage.py`
and type this command:
.. code-block:: console
$ python manage.py startapp polls
That'll create a directory :file:`polls`, which is laid out like this::
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
This directory structure will house the poll application.
Write your first view
=====================
Let's write the first view. Open the file ``polls/views.py``
and put the following Python code in it:
.. snippet::
:filename: polls/views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the polls index.")
This is the simplest view possible in Django. To call the view, we need to map
it to a URL - and for this we need a URLconf.
To create a URLconf in the polls directory, create a file called ``urls.py``.
Your app directory should now look like::
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
urls.py
views.py
In the ``polls/urls.py`` file include the following code:
.. snippet::
:filename: polls/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
]
The next step is to point the root URLconf at the ``polls.urls`` module. In
``mysite/urls.py``, add an import for ``django.conf.urls.include`` and insert
an :func:`~django.conf.urls.include` in the ``urlpatterns`` list, so you have:
.. snippet::
:filename: mysite/urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^polls/', include('polls.urls')),
url(r'^admin/', admin.site.urls),
]
The :func:`~django.conf.urls.include` function allows referencing other
URLconfs. Note that the regular expressions for the
:func:`~django.conf.urls.include` function doesn't have a ``$`` (end-of-string
match character) but rather a trailing slash. Whenever Django encounters
:func:`~django.conf.urls.include`, it chops off whatever part of the URL
matched up to that point and sends the remaining string to the included URLconf
for further processing.
The idea behind :func:`~django.conf.urls.include` is to make it easy to
plug-and-play URLs. Since polls are in their own URLconf
(``polls/urls.py``), they can be placed under "/polls/", or under
"/fun_polls/", or under "/content/polls/", or any other path root, and the
app will still work.
.. admonition:: When to use :func:`~django.conf.urls.include()`
You should always use ``include()`` when you include other URL patterns.
``admin.site.urls`` is the only exception to this.
.. admonition:: Doesn't match what you see?
If you're seeing ``include(admin.site.urls)`` instead of just
``admin.site.urls``, you're probably using a version of Django that
doesn't match this tutorial version. You'll want to either switch to the
older tutorial or the newer Django version.
You have now wired an ``index`` view into the URLconf. Lets verify it's
working, run the following command:
.. code-block:: console
$ python manage.py runserver
Go to http://localhost:8000/polls/ in your browser, and you should see the
text "*Hello, world. You're at the polls index.*", which you defined in the
``index`` view.
The :func:`~django.conf.urls.url` function is passed four arguments, two
required: ``regex`` and ``view``, and two optional: ``kwargs``, and ``name``.
At this point, it's worth reviewing what these arguments are for.
:func:`~django.conf.urls.url` argument: regex
---------------------------------------------
The term "regex" is a commonly used short form meaning "regular expression",
which is a syntax for matching patterns in strings, or in this case, url
patterns. Django starts at the first regular expression and makes its way down
the list, comparing the requested URL against each regular expression until it
finds one that matches.
Note that these regular expressions do not search GET and POST parameters, or
the domain name. For example, in a request to
``https://www.example.com/myapp/``, the URLconf will look for ``myapp/``. In a
request to ``https://www.example.com/myapp/?page=3``, the URLconf will also
look for ``myapp/``.
If you need help with regular expressions, see `Wikipedia's entry`_ and the
documentation of the :mod:`re` module. Also, the O'Reilly book "Mastering
Regular Expressions" by Jeffrey Friedl is fantastic. In practice, however,
you don't need to be an expert on regular expressions, as you really only need
to know how to capture simple patterns. In fact, complex regexes can have poor
lookup performance, so you probably shouldn't rely on the full power of regexes.
Finally, a performance note: these regular expressions are compiled the first
time the URLconf module is loaded. They're super fast (as long as the lookups
aren't too complex as noted above).
.. _Wikipedia's entry: https://en.wikipedia.org/wiki/Regular_expression
:func:`~django.conf.urls.url` argument: view
--------------------------------------------
When Django finds a regular expression match, Django calls the specified view
function, with an :class:`~django.http.HttpRequest` object as the first
argument and any “captured” values from the regular expression as other
arguments. If the regex uses simple captures, values are passed as positional
arguments; if it uses named captures, values are passed as keyword arguments.
We'll give an example of this in a bit.
:func:`~django.conf.urls.url` argument: kwargs
----------------------------------------------
Arbitrary keyword arguments can be passed in a dictionary to the target view. We
aren't going to use this feature of Django in the tutorial.
:func:`~django.conf.urls.url` argument: name
---------------------------------------------
Naming your URL lets you refer to it unambiguously from elsewhere in Django,
especially from within templates. This powerful feature allows you to make
global changes to the URL patterns of your project while only touching a single
file.
When you're comfortable with the basic request and response flow, read
:doc:`part 2 of this tutorial ` to start working with the
database.
---
### 大一小学期 Week 3 Python Exam 2016 Docs Intro Tutorial02 (`大一小学期/Week_3-Python/exam/2016/docs/intro/tutorial02.txt`)
=====================================
Writing your first Django app, part 2
=====================================
This tutorial begins where :doc:`Tutorial 1 ` left off.
We'll setup the database, create your first model, and get a quick introduction
to Django's automatically-generated admin site.
Database setup
==============
Now, open up :file:`mysite/settings.py`. It's a normal Python module with
module-level variables representing Django settings.
By default, the configuration uses SQLite. If you're new to databases, or
you're just interested in trying Django, this is the easiest choice. SQLite is
included in Python, so you won't need to install anything else to support your
database. When starting your first real project, however, you may want to use a
more robust database like PostgreSQL, to avoid database-switching headaches
down the road.
If you wish to use another database, install the appropriate :ref:`database
bindings <database-installation>` and change the following keys in the
:setting:`DATABASES` ``'default'`` item to match your database connection
settings:
* :setting:`ENGINE <DATABASE-ENGINE>` -- Either
``'django.db.backends.sqlite3'``,
``'django.db.backends.postgresql'``,
``'django.db.backends.mysql'``, or
``'django.db.backends.oracle'``. Other backends are :ref:`also available
`.
* :setting:`NAME` -- The name of your database. If you're using SQLite, the
database will be a file on your computer; in that case, :setting:`NAME`
should be the full absolute path, including filename, of that file. The
default value, ``os.path.join(BASE_DIR, 'db.sqlite3')``, will store the file
in your project directory.
If you are not using SQLite as your database, additional settings such as
:setting:`USER`, :setting:`PASSWORD`, and :setting:`HOST` must be added.
For more details, see the reference documentation for :setting:`DATABASES`.
.. admonition:: For databases other than SQLite
If you're using a database besides SQLite, make sure you've created a
database by this point. Do that with "``CREATE DATABASE database_name;``"
within your database's interactive prompt.
Also make sure that the database user provided in :file:`mysite/settings.py`
has "create database" privileges. This allows automatic creation of a
:ref:`test database ` which will be needed in a later
tutorial.
If you're using SQLite, you don't need to create anything beforehand - the
database file will be created automatically when it is needed.
While you're editing :file:`mysite/settings.py`, set :setting:`TIME_ZONE` to
your time zone.
Also, note the :setting:`INSTALLED_APPS` setting at the top of the file. That
holds the names of all Django applications that are activated in this Django
instance. Apps can be used in multiple projects, and you can package and
distribute them for use by others in their projects.
By default, :setting:`INSTALLED_APPS` contains the following apps, all of which
come with Django:
* :mod:`django.contrib.admin` -- The admin site. You'll use it shortly.
* :mod:`django.contrib.auth` -- An authentication system.
* :mod:`django.contrib.contenttypes` -- A framework for content types.
* :mod:`django.contrib.sessions` -- A session framework.
* :mod:`django.contrib.messages` -- A messaging framework.
* :mod:`django.contrib.staticfiles` -- A framework for managing
static files.
These applications are included by default as a convenience for the common case.
Some of these applications make use of at least one database table, though,
so we need to create the tables in the database before we can use them. To do
that, run the following command:
.. code-block:: console
$ python manage.py migrate
The :djadmin:`migrate` command looks at the :setting:`INSTALLED_APPS` setting
and creates any necessary database tables according to the database settings
in your :file:`mysite/settings.py` file and the database migrations shipped
with the app (we'll cover those later). You'll see a message for each
migration it applies. If you're interested, run the command-line client for your
database and type ``\dt`` (PostgreSQL), ``SHOW TABLES;`` (MySQL), ``.schema``
(SQLite), or ``SELECT TABLE_NAME FROM USER_TABLES;`` (Oracle) to display the
tables Django created.
.. admonition:: For the minimalists
Like we said above, the default applications are included for the common
case, but not everybody needs them. If you don't need any or all of them,
feel free to comment-out or delete the appropriate line(s) from
:setting:`INSTALLED_APPS` before running :djadmin:`migrate`. The
:djadmin:`migrate` command will only run migrations for apps in
:setting:`INSTALLED_APPS`.
.. _creating-models:
Creating models
===============
Now we'll define your models -- essentially, your database layout, with
additional metadata.
.. admonition:: Philosophy
A model is the single, definitive source of truth about your data. It contains
the essential fields and behaviors of the data you're storing. Django follows
the :ref:`DRY Principle <dry>`. The goal is to define your data model in one
place and automatically derive things from it.
This includes the migrations - unlike in Ruby On Rails, for example, migrations
are entirely derived from your models file, and are essentially just a
history that Django can roll through to update your database schema to
match your current models.
In our simple poll app, we'll create two models: ``Question`` and ``Choice``.
A ``Question`` has a question and a publication date. A ``Choice`` has two
fields: the text of the choice and a vote tally. Each ``Choice`` is associated
with a ``Question``.
These concepts are represented by simple Python classes. Edit the
:file:`polls/models.py` file so it looks like this:
.. snippet::
:filename: polls/models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
The code is straightforward. Each model is represented by a class that
subclasses :class:`django.db.models.Model`. Each model has a number of class
variables, each of which represents a database field in the model.
Each field is represented by an instance of a :class:`~django.db.models.Field`
class -- e.g., :class:`~django.db.models.CharField` for character fields and
:class:`~django.db.models.DateTimeField` for datetimes. This tells Django what
type of data each field holds.
The name of each :class:`~django.db.models.Field` instance (e.g.
``question_text`` or ``pub_date``) is the field's name, in machine-friendly
format. You'll use this value in your Python code, and your database will use
it as the column name.
You can use an optional first positional argument to a
:class:`~django.db.models.Field` to designate a human-readable name. That's used
in a couple of introspective parts of Django, and it doubles as documentation.
If this field isn't provided, Django will use the machine-readable name. In this
example, we've only defined a human-readable name for ``Question.pub_date``.
For all other fields in this model, the field's machine-readable name will
suffice as its human-readable name.
Some :class:`~django.db.models.Field` classes have required arguments.
:class:`~django.db.models.CharField`, for example, requires that you give it a
:attr:`~django.db.models.CharField.max_length`. That's used not only in the
database schema, but in validation, as we'll soon see.
A :class:`~django.db.models.Field` can also have various optional arguments; in
this case, we've set the :attr:`~django.db.models.Field.default` value of
``votes`` to 0.
Finally, note a relationship is defined, using
:class:`~django.db.models.ForeignKey`. That tells Django each ``Choice`` is
related to a single ``Question``. Django supports all the common database
relationships: many-to-one, many-to-many, and one-to-one.
Activating models
=================
That small bit of model code gives Django a lot of information. With it, Django
is able to:
* Create a database schema (``CREATE TABLE`` statements) for this app.
* Create a Python database-access API for accessing ``Question`` and ``Choice`` objects.
But first we need to tell our project that the ``polls`` app is installed.
.. admonition:: Philosophy
Django apps are "pluggable": You can use an app in multiple projects, and
you can distribute apps, because they don't have to be tied to a given
Django installation.
Edit the :file:`mysite/settings.py` file again, and change the
:setting:`INSTALLED_APPS` setting to include the string
``'polls.apps.PollsConfig'``. It'll look like this:
.. snippet::
:filename: mysite/settings.py
INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
Now Django knows to include the ``polls`` app. Let's run another command:
.. code-block:: console
$ python manage.py makemigrations polls
You should see something similar to the following:
.. code-block:: text
Migrations for 'polls':
polls/migrations/0001_initial.py:
- Create model Choice
- Create model Question
- Add field question to choice
By running ``makemigrations``, you're telling Django that you've made
some changes to your models (in this case, you've made new ones) and that
you'd like the changes to be stored as a *migration*.
Migrations are how Django stores changes to your models (and thus your
database schema) - they're just files on disk. You can read the migration
for your new model if you like; it's the file
``polls/migrations/0001_initial.py``. Don't worry, you're not expected to read
them every time Django makes one, but they're designed to be human-editable
in case you want to manually tweak how Django changes things.
There's a command that will run the migrations for you and manage your database
schema automatically - that's called :djadmin:`migrate`, and we'll come to it in a
moment - but first, let's see what SQL that migration would run. The
:djadmin:`sqlmigrate` command takes migration names and returns their SQL:
.. code-block:: console
$ python manage.py sqlmigrate polls 0001
You should see something similar to the following (we've reformatted it for
readability):
.. code-block:: sql
BEGIN;
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
"id" serial NOT NULL PRIMARY KEY,
"choice_text" varchar(200) NOT NULL,
"votes" integer NOT NULL
);
--
-- Create model Question
--
CREATE TABLE "polls_question" (
"id" serial NOT NULL PRIMARY KEY,
"question_text" varchar(200) NOT NULL,
"pub_date" timestamp with time zone NOT NULL
);
--
-- Add field question to choice
--
ALTER TABLE "polls_choice" ADD COLUMN "question_id" integer NOT NULL;
ALTER TABLE "polls_choice" ALTER COLUMN "question_id" DROP DEFAULT;
CREATE INDEX "polls_choice_7aa0f6ee" ON "polls_choice" ("question_id");
ALTER TABLE "polls_choice"
ADD CONSTRAINT "polls_choice_question_id_246c99a640fbbd72_fk_polls_question_id"
FOREIGN KEY ("question_id")
REFERENCES "polls_question" ("id")
DEFERRABLE INITIALLY DEFERRED;
COMMIT;
Note the following:
* The exact output will vary depending on the database you are using. The
example above is generated for PostgreSQL.
* Table names are automatically generated by combining the name of the app
(``polls``) and the lowercase name of the model -- ``question`` and
``choice``. (You can override this behavior.)
* Primary keys (IDs) are added automatically. (You can override this, too.)
* By convention, Django appends ``"_id"`` to the foreign key field name.
(Yes, you can override this, as well.)
* The foreign key relationship is made explicit by a ``FOREIGN KEY``
constraint. Don't worry about the ``DEFERRABLE`` parts; that's just telling
PostgreSQL to not enforce the foreign key until the end of the transaction.
* It's tailored to the database you're using, so database-specific field types
such as ``auto_increment`` (MySQL), ``serial`` (PostgreSQL), or ``integer
primary key autoincrement`` (SQLite) are handled for you automatically. Same
goes for the quoting of field names -- e.g., using double quotes or
single quotes.
* The :djadmin:`sqlmigrate` command doesn't actually run the migration on your
database - it just prints it to the screen so that you can see what SQL
Django thinks is required. It's useful for checking what Django is going to
do or if you have database administrators who require SQL scripts for
changes.
If you're interested, you can also run
:djadmin:`python manage.py check <check>`; this checks for any problems in
your project without making migrations or touching the database.
Now, run :djadmin:`migrate` again to create those model tables in your database:
.. code-block:: console
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Rendering model states... DONE
Applying polls.0001_initial... OK
The :djadmin:`migrate` command takes all the migrations that haven't been
applied (Django tracks which ones are applied using a special table in your
database called ``django_migrations``) and runs them against your database -
essentially, synchronizing the changes you made to your models with the schema
in the database.
Migrations are very powerful and let you change your models over time, as you
develop your project, without the need to delete your database or tables and
make new ones - it specializes in upgrading your database live, without
losing data. We'll cover them in more depth in a later part of the tutorial,
but for now, remember the three-step guide to making model changes:
* Change your models (in ``models.py``).
* Run :djadmin:`python manage.py makemigrations <makemigrations>` to create
migrations for those changes
* Run :djadmin:`python manage.py migrate <migrate>` to apply those changes to
the database.
The reason that there are separate commands to make and apply migrations is
because you'll commit migrations to your version control system and ship them
with your app; they not only make your development easier, they're also
useable by other developers and in production.
Read the :doc:`django-admin documentation </ref/django-admin>` for full
information on what the ``manage.py`` utility can do.
Playing with the API
====================
Now, let's hop into the interactive Python shell and play around with the free
API Django gives you. To invoke the Python shell, use this command:
.. code-block:: console
$ python manage.py shell
We're using this instead of simply typing "python", because :file:`manage.py`
sets the ``DJANGO_SETTINGS_MODULE`` environment variable, which gives Django
the Python import path to your :file:`mysite/settings.py` file.
.. admonition:: Bypassing manage.py
If you'd rather not use :file:`manage.py`, no problem. Just set the
:envvar:`DJANGO_SETTINGS_MODULE` environment variable to
``mysite.settings``, start a plain Python shell, and set up Django:
.. code-block:: pycon
>>> import django
>>> django.setup()
If this raises an :exc:`AttributeError`, you're probably using
a version of Django that doesn't match this tutorial version. You'll want
to either switch to the older tutorial or the newer Django version.
You must run ``python`` from the same directory :file:`manage.py` is in,
or ensure that directory is on the Python path, so that ``import mysite``
works.
For more information on all of this, see the :doc:`django-admin
documentation </ref/django-admin>`.
Once you're in the shell, explore the :doc:`database API </topics/db/queries>`::
>>> from polls.models import Question, Choice # Import the model classes we just wrote.
# No questions are in the system yet.
>>> Question.objects.all()
<QuerySet []>
# Create a new Question.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())
# Save the object into the database. You have to call save() explicitly.
>>> q.save()
# Now it has an ID. Note that this might say "1L" instead of "1", depending
# on which database you're using. That's no biggie; it just means your
# database backend prefers to return integers as Python long integer
# objects.
>>> q.id
1
# Access model field values via Python attributes.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=)
# Change values by changing the attributes, then calling save().
>>> q.question_text = "What's up?"
>>> q.save()
# objects.all() displays all the questions in the database.
>>> Question.objects.all()
<QuerySet [<Question: Question object>]>
Wait a minute. ``<Question: Question object>`` is, utterly, an unhelpful representation
of this object. Let's fix that by editing the ``Question`` model (in the
``polls/models.py`` file) and adding a
:meth:`~django.db.models.Model.__str__` method to both ``Question`` and
``Choice``:
.. snippet::
:filename: polls/models.py
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible # only if you need to support Python 2
class Question(models.Model):
# ...
def __str__(self):
return self.question_text
@python_2_unicode_compatible # only if you need to support Python 2
class Choice(models.Model):
# ...
def __str__(self):
return self.choice_text
It's important to add :meth:`~django.db.models.Model.__str__` methods to your
models, not only for your own convenience when dealing with the interactive
prompt, but also because objects' representations are used throughout Django's
automatically-generated admin.
Note these are normal Python methods. Let's add a custom method, just for
demonstration:
.. snippet::
:filename: polls/models.py
import datetime
from django.db import models
from django.utils import timezone
class Question(models.Model):
# ...
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
Note the addition of ``import datetime`` and ``from django.utils import
timezone``, to reference Python's standard :mod:`datetime` module and Django's
time-zone-related utilities in :mod:`django.utils.timezone`, respectively. If
you aren't familiar with time zone handling in Python, you can learn more in
the :doc:`time zone support docs </topics/i18n/timezones>`.
Save these changes and start a new Python interactive shell by running
``python manage.py shell`` again::
>>> from polls.models import Question, Choice
# Make sure our __str__() addition worked.
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>
# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>
# Get the question that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>
# Request an ID that doesn't exist, this will raise an exception.
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Question matching query does not exist.
# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Question.objects.get(id=1).
>>> Question.objects.get(pk=1)
<Question: What's up?>
# Make sure our custom method worked.
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True
# Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a question's choice) which can be accessed via the API.
>>> q = Question.objects.get(pk=1)
# Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
<QuerySet []>
# Create three choices.
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)
# Choice objects have API access to their related Question objects.
>>> c.question
<Question: What's up?>
# And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3
# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
# Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()
For more information on model relations, see :doc:`Accessing related objects
</ref/models/relations>`. For more on how to use double underscores to perform
field lookups via the API, see :ref:`Field lookups <field-lookups-intro>`. For
full details on the database API, see our :doc:`Database API reference
</topics/db/queries>`.
Introducing the Django Admin
============================
.. admonition:: Philosophy
Generating admin sites for your staff or clients to add, change, and delete
content is tedious work that doesn't require much creativity. For that
reason, Django entirely automates creation of admin interfaces for models.
Django was written in a newsroom environment, with a very clear separation
between "content publishers" and the "public" site. Site managers use the
system to add news stories, events, sports scores, etc., and that content is
displayed on the public site. Django solves the problem of creating a
unified interface for site administrators to edit content.
The admin isn't intended to be used by site visitors. It's for site
managers.
Creating an admin user
----------------------
First we'll need to create a user who can login to the admin site. Run the
following command:
.. code-block:: console
$ python manage.py createsuperuser
Enter your desired username and press enter.
.. code-block:: text
Username: admin
You will then be prompted for your desired email address:
.. code-block:: text
Email address: [email protected]
The final step is to enter your password. You will be asked to enter your
password twice, the second time as a confirmation of the first.
.. code-block:: text
Password: **********
Password (again): *********
Superuser created successfully.
Start the development server
----------------------------
The Django admin site is activated by default. Let's start the development
server and explore it.
If the server is not running start it like so:
.. code-block:: console
$ python manage.py runserver
Now, open a Web browser and go to "/admin/" on your local domain -- e.g.,
http://127.0.0.1:8000/admin/. You should see the admin's login screen:
.. image:: _images/admin01.png
:alt: Django admin login screen
Since :doc:`translation </topics/i18n/translation>` is turned on by default,
the login screen may be displayed in your own language, depending on your
browser's settings and if Django has a translation for this language.
Enter the admin site
--------------------
Now, try logging in with the superuser account you created in the previous step.
You should see the Django admin index page:
.. image:: _images/admin02.png
:alt: Django admin index page
You should see a few types of editable content: groups and users. They are
provided by :mod:`django.contrib.auth`, the authentication framework shipped
by Django.
Make the poll app modifiable in the admin
-----------------------------------------
But where's our poll app? It's not displayed on the admin index page.
Just one thing to do: we need to tell the admin that ``Question``
objects have an admin interface. To do this, open the :file:`polls/admin.py`
file, and edit it to look like this:
.. snippet::
:filename: polls/admin.py
from django.contrib import admin
from .models import Question
admin.site.register(Question)
Explore the free admin functionality
------------------------------------
Now that we've registered ``Question``, Django knows that it should be displayed on
the admin index page:
.. image:: _images/admin03t.png
:alt: Django admin index page, now with polls displayed
Click "Questions". Now you're at the "change list" page for questions. This page
displays all the questions in the database and lets you choose one to change it.
There's the "What's up?" question we created earlier:
.. image:: _images/admin04t.png
:alt: Polls change list page
Click the "What's up?" question to edit it:
.. image:: _images/admin05t.png
:alt: Editing form for question object
Things to note here:
* The form is automatically generated from the ``Question`` model.
* The different model field types (:class:`~django.db.models.DateTimeField`,
:class:`~django.db.models.CharField`) correspond to the appropriate HTML
input widget. Each type of field knows how to display itself in the Django
admin.
* Each :class:`~django.db.models.DateTimeField` gets free JavaScript
shortcuts. Dates get a "Today" shortcut and calendar popup, and times get
a "Now" shortcut and a convenient popup that lists commonly entered times.
The bottom part of the page gives you a couple of options:
* Save -- Saves changes and returns to the change-list page for this type of
object.
* Save and continue editing -- Saves changes and reloads the admin page for
this object.
* Save and add another -- Saves changes and loads a new, blank form for this
type of object.
* Delete -- Displays a delete confirmation page.
If the value of "Date published" doesn't match the time when you created the
question in :doc:`Tutorial 1`, it probably
means you forgot to set the correct value for the :setting:`TIME_ZONE` setting.
Change it, reload the page and check that the correct value appears.
Change the "Date published" by clicking the "Today" and "Now" shortcuts. Then
click "Save and continue editing." Then click "History" in the upper right.
You'll see a page listing all changes made to this object via the Django admin,
with the timestamp and username of the person who made the change:
.. image:: _images/admin06t.png
:alt: History page for question object
When you're comfortable with the models API and have familiarized yourself with
the admin site, read :doc:`part 3 of this tutorial` to learn
about how to add more views to our polls app.
---
### 大一小学期 Week 3 Python Exam 2016 Docs Intro Tutorial03 (`大一小学期/Week_3-Python/exam/2016/docs/intro/tutorial03.txt`)
=====================================
Writing your first Django app, part 3
=====================================
This tutorial begins where :doc:`Tutorial 2 ` left off. We're
continuing the Web-poll application and will focus on creating the public
interface -- "views."
Overview
========
A view is a "type" of Web page in your Django application that generally serves
a specific function and has a specific template. For example, in a blog
application, you might have the following views:
* Blog homepage -- displays the latest few entries.
* Entry "detail" page -- permalink page for a single entry.
* Year-based archive page -- displays all months with entries in the
given year.
* Month-based archive page -- displays all days with entries in the
given month.
* Day-based archive page -- displays all entries in the given day.
* Comment action -- handles posting comments to a given entry.
In our poll application, we'll have the following four views:
* Question "index" page -- displays the latest few questions.
* Question "detail" page -- displays a question text, with no results but
with a form to vote.
* Question "results" page -- displays results for a particular question.
* Vote action -- handles voting for a particular choice in a particular
question.
In Django, web pages and other content are delivered by views. Each view is
represented by a simple Python function (or method, in the case of class-based
views). Django will choose a view by examining the URL that's requested (to be
precise, the part of the URL after the domain name).
Now in your time on the web you may have come across such beauties as
"ME2/Sites/dirmod.asp?sid=&type=gen&mod=Core+Pages&gid=A6CD4967199A42D9B65B1B".
You will be pleased to know that Django allows us much more elegant
*URL patterns* than that.
A URL pattern is simply the general form of a URL - for example:
``/newsarchive/<year>/<month>/``.
To get from a URL to a view, Django uses what are known as 'URLconfs'. A
URLconf maps URL patterns (described as regular expressions) to views.
This tutorial provides basic instruction in the use of URLconfs, and you can
refer to :mod:`django.urls` for more information.
Writing more views
==================
Now let's add a few more views to ``polls/views.py``. These views are
slightly different, because they take an argument:
.. snippet::
:filename: polls/views.py
def detail(request, question_id):
return HttpResponse("You're looking at question %s." % question_id)
def results(request, question_id):
response = "You're looking at the results of question %s."
return HttpResponse(response % question_id)
def vote(request, question_id):
return HttpResponse("You're voting on question %s." % question_id)
Wire these new views into the ``polls.urls`` module by adding the following
:func:`~django.conf.urls.url` calls:
.. snippet::
:filename: polls/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
# ex: /polls/
url(r'^$', views.index, name='index'),
# ex: /polls/5/
url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
# ex: /polls/5/results/
url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
# ex: /polls/5/vote/
url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]
Take a look in your browser, at "/polls/34/". It'll run the ``detail()``
method and display whatever ID you provide in the URL. Try
"/polls/34/results/" and "/polls/34/vote/" too -- these will display the
placeholder results and voting pages.
When somebody requests a page from your website -- say, "/polls/34/", Django
will load the ``mysite.urls`` Python module because it's pointed to by the
:setting:`ROOT_URLCONF` setting. It finds the variable named ``urlpatterns``
and traverses the regular expressions in order. After finding the match at
``'^polls/'``, it strips off the matching text (``"polls/"``) and sends the
remaining text -- ``"34/"`` -- to the 'polls.urls' URLconf for further
processing. There it matches ``r'^(?P<question_id>[0-9]+)/$'``, resulting in a
call to the ``detail()`` view like so::
detail(request=<HttpRequest object>, question_id='34')
The ``question_id='34'`` part comes from ``(?P<question_id>[0-9]+)``. Using parentheses
around a pattern "captures" the text matched by that pattern and sends it as an
argument to the view function; ``?P<question_id>`` defines the name that will
be used to identify the matched pattern; and ``[0-9]+`` is a regular expression to
match a sequence of digits (i.e., a number).
Because the URL patterns are regular expressions, there really is no limit on
what you can do with them. And there's no need to add URL cruft such as
``.html`` -- unless you want to, in which case you can do something like
this::
url(r'^polls/latest\.html$', views.index),
But, don't do that. It's silly.
Write views that actually do something
======================================
Each view is responsible for doing one of two things: returning an
:class:`~django.http.HttpResponse` object containing the content for the
requested page, or raising an exception such as :exc:`~django.http.Http404`. The
rest is up to you.
Your view can read records from a database, or not. It can use a template
system such as Django's -- or a third-party Python template system -- or not.
It can generate a PDF file, output XML, create a ZIP file on the fly, anything
you want, using whatever Python libraries you want.
All Django wants is that :class:`~django.http.HttpResponse`. Or an exception.
Because it's convenient, let's use Django's own database API, which we covered
in :doc:`Tutorial 2 `. Here's one stab at a new ``index()``
view, which displays the latest 5 poll questions in the system, separated by
commas, according to publication date:
.. snippet::
:filename: polls/views.py
from django.http import HttpResponse
from .models import Question
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
output = ', '.join([q.question_text for q in latest_question_list])
return HttpResponse(output)
# Leave the rest of the views (detail, results, vote) unchanged
There's a problem here, though: the page's design is hard-coded in the view. If
you want to change the way the page looks, you'll have to edit this Python code.
So let's use Django's template system to separate the design from Python by
creating a template that the view can use.
First, create a directory called ``templates`` in your ``polls`` directory.
Django will look for templates in there.
Your project's :setting:`TEMPLATES` setting describes how Django will load and
render templates. The default settings file configures a ``DjangoTemplates``
backend whose :setting:`APP_DIRS <TEMPLATES-APP_DIRS>` option is set to
``True``. By convention ``DjangoTemplates`` looks for a "templates"
subdirectory in each of the :setting:`INSTALLED_APPS`.
Within the ``templates`` directory you have just created, create another
directory called ``polls``, and within that create a file called
``index.html``. In other words, your template should be at
``polls/templates/polls/index.html``. Because of how the ``app_directories``
template loader works as described above, you can refer to this template within
Django simply as ``polls/index.html``.
.. admonition:: Template namespacing
Now we *might* be able to get away with putting our templates directly in
``polls/templates`` (rather than creating another ``polls`` subdirectory),
but it would actually be a bad idea. Django will choose the first template
it finds whose name matches, and if you had a template with the same name
in a *different* application, Django would be unable to distinguish between
them. We need to be able to point Django at the right one, and the easiest
way to ensure this is by *namespacing* them. That is, by putting those
templates inside *another* directory named for the application itself.
Put the following code in that template:
.. snippet:: html+django
:filename: polls/templates/polls/index.html
{% if latest_question_list %}
{% for question in latest_question_list %}
<li>[{{ question.question_text }}](/polls/{{ question.id }}/)</li>
{% endfor %}
{% else %}
No polls are available.
{% endif %}
Now let's update our ``index`` view in ``polls/views.py`` to use the template:
.. snippet::
:filename: polls/views.py
from django.http import HttpResponse
from django.template import loader
from .models import Question
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
template = loader.get_template('polls/index.html')
context = {
'latest_question_list': latest_question_list,
}
return HttpResponse(template.render(context, request))
That code loads the template called ``polls/index.html`` and passes it a
context. The context is a dictionary mapping template variable names to Python
objects.
Load the page by pointing your browser at "/polls/", and you should see a
bulleted-list containing the "What's up" question from :doc:`Tutorial 2
`. The link points to the question's detail page.
A shortcut: :func:`~django.shortcuts.render`
--------------------------------------------
It's a very common idiom to load a template, fill a context and return an
:class:`~django.http.HttpResponse` object with the result of the rendered
template. Django provides a shortcut. Here's the full ``index()`` view,
rewritten:
.. snippet::
:filename: polls/views.py
from django.shortcuts import render
from .models import Question
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)
Note that once we've done this in all these views, we no longer need to import
:mod:`~django.template.loader` and :class:`~django.http.HttpResponse` (you'll
want to keep ``HttpResponse`` if you still have the stub methods for ``detail``,
``results``, and ``vote``).
The :func:`~django.shortcuts.render` function takes the request object as its
first argument, a template name as its second argument and a dictionary as its
optional third argument. It returns an :class:`~django.http.HttpResponse`
object of the given template rendered with the given context.
Raising a 404 error
===================
Now, let's tackle the question detail view -- the page that displays the question text
for a given poll. Here's the view:
.. snippet::
:filename: polls/views.py
from django.http import Http404
from django.shortcuts import render
from .models import Question
# ...
def detail(request, question_id):
try:
question = Question.objects.get(pk=question_id)
except Question.DoesNotExist:
raise Http404("Question does not exist")
return render(request, 'polls/detail.html', {'question': question})
The new concept here: The view raises the :exc:`~django.http.Http404` exception
if a question with the requested ID doesn't exist.
We'll discuss what you could put in that ``polls/detail.html`` template a bit
later, but if you'd like to quickly get the above example working, a file
containing just:
.. snippet:: html+django
:filename: polls/templates/polls/detail.html
{{ question }}
will get you started for now.
A shortcut: :func:`~django.shortcuts.get_object_or_404`
-------------------------------------------------------
It's a very common idiom to use :meth:`~django.db.models.query.QuerySet.get`
and raise :exc:`~django.http.Htt