- Django 教程
- 姜戈 - 主页
- Django - 基础知识
- Django - 概述
- Django - 环境
- Django - 创建项目
- Django - 应用程序生命周期
- Django - 管理界面
- Django - 创建视图
- Django - URL 映射
- Django - 模板系统
- Django - 模型
- Django - 页面重定向
- Django - 发送电子邮件
- Django - 通用视图
- Django - 表单处理
- Django - 文件上传
- Django - Apache 设置
- Django - Cookie 处理
- Django - 会话
- Django - 缓存
- Django - 评论
- 姜戈 - RSS
- Django - AJAX
- Django 有用资源
- Django - 快速指南
- Django - 有用的资源
- Django - 讨论
Django - 快速指南
Django - 基础知识
Django 是一个高级 Python Web 框架,鼓励快速开发和简洁、务实的设计。Django 可以更轻松地使用更少的代码快速构建更好的 Web 应用程序。
注意- Django 是 Django Software Foundation 的注册商标,并根据 BSD 许可证获得许可。
姜戈的历史
2003 年– 由 Adrian Holovaty 和 Simon Willison 发起,作为《劳伦斯世界日报》的内部项目。
2005 – 2005 年 7 月发布,并以爵士吉他手 Django Reinhardt 的名字命名为 Django。
2005 - 足够成熟,可以处理多个高流量站点。
当前- Django 现在是一个开源项目,贡献者遍布世界各地。
Django——设计哲学
Django 具有以下设计理念 -
松散耦合- Django 的目标是使其堆栈中的每个元素独立于其他元素。
更少的编码- 更少的代码,因此可以快速开发。
不要重复自己(DRY) ——一切都应该只在一个地方开发,而不是一次又一次地重复。
快速开发- Django 的理念是尽一切努力促进超快速开发。
干净的设计- Django 在其自己的代码中严格维护干净的设计,并使遵循最佳 Web 开发实践变得容易。
Django的优点
以下是使用 Django 的一些优点,可以在此处列出 -
对象关系映射(ORM)支持- Django 提供了数据模型和数据库引擎之间的桥梁,并支持大量数据库系统,包括 MySQL、Oracle、Postgres 等。Django 还通过 Django-nonrel fork 支持 NoSQL 数据库。目前,唯一支持的 NoSQL 数据库是 MongoDB 和 Google App Engine。
多语言支持- Django 通过其内置的国际化系统支持多语言网站。因此您可以开发支持多种语言的网站。
框架支持- Django 内置了对 Ajax、RSS、缓存和各种其他框架的支持。
管理 GUI - Django 为管理活动提供了一个很好的即用型用户界面。
开发环境- Django 附带一个轻量级 Web 服务器,以促进端到端应用程序开发和测试。
Django - 概述
如您所知,Django 是一个 Python Web 框架。与大多数现代框架一样,Django 支持 MVC 模式。首先让我们看看什么是模型-视图-控制器 (MVC) 模式,然后我们将了解 Django 对模型-视图-模板 (MVT) 模式的特殊性。
MVC模式
当谈论提供UI(Web或桌面)的应用程序时,我们通常谈论MVC架构。顾名思义,MVC 模式基于三个组件:模型、视图和控制器。请在此处查看我们的 MVC 教程以了解更多信息。
DJANGO MVC - MVT 模式
模型-视图-模板 (MVT) 与 MVC 略有不同。事实上,这两种模式之间的主要区别在于 Django 本身负责控制器部分(控制模型和视图之间交互的软件代码),而留给我们模板。该模板是与 Django 模板语言 (DTL) 混合的 HTML 文件。
下图说明了 MVT 模式的每个组件如何相互交互以服务用户请求 -
开发人员提供模型、视图和模板,然后将其映射到 URL,Django 会神奇地将其提供给用户。
Django - 环境
Django 开发环境包括安装和设置Python、Django 和数据库系统。由于 Django 处理 Web 应用程序,因此值得一提的是,您还需要设置 Web 服务器。
第 1 步 – 安装 Python
Django 是用 100% 纯 Python 代码编写的,因此您需要在系统上安装 Python。最新的 Django 版本需要 Python 2.6.5 或更高版本(对于 2.6.x 分支)或高于 2.7.3(对于 2.7.x 分支)。
如果您使用的是最新的 Linux 或 Mac OS X 发行版之一,那么您可能已经安装了 Python。您可以通过在命令提示符下键入python命令来验证它。如果您看到类似这样的内容,则说明 Python 已安装。
$ python Python 2.7.5 (default, Jun 17 2014, 18:11:42) [GCC 4.8.2 20140120 (Red Hat 4.8.2-16)] on linux2
否则,您可以从链接http://www.python.org/download下载并安装最新版本的 Python 。
第 2 步 - 安装 Django
安装 Django 非常简单,但安装所需的步骤取决于您的操作系统。由于 Python 是一种独立于平台的语言,因此 Django 拥有一个可以在任何地方运行的包,无论您的操作系统如何。
您可以从链接http://www.djangoproject.com/download下载最新版本的 Django 。
UNIX/Linux 和 Mac OS X 安装
如果您运行的是 Linux 或 Mac OS 系统,您有两种安装 Django 的方法 -
您可以使用操作系统的包管理器,或者使用 easy_install 或 pip(如果已安装)。
使用您之前下载的官方存档手动安装它。
我们将介绍第二个选项,因为第一个选项取决于您的操作系统发行版。如果您决定遵循第一个选项,请注意您正在安装的 Django 版本。
假设您从上面的链接获取了存档,它应该类似于 Django-x.xx.tar.gz:
解压并安装。
$ tar xzvf Django-x.xx.tar.gz $ cd Django-x.xx $ sudo python setup.py install
您可以通过运行此命令来测试您的安装 -
$ django-admin.py --version
如果您看到屏幕上打印了 Django 的当前版本,则一切都已设置。
注意- 对于某些版本的 Django,django-admin 中的“.py”将被删除。
Windows安装
我们假设您的计算机上安装了 Django 存档和 python。
首先,PATH验证。
在某些版本的 Windows(Windows 7)上,您可能需要确保 Path 系统变量具有以下路径 C:\Python27\;C:\Python27\Lib\site-packages\django\bin\
,当然取决于您的 Python 版本。
然后,解压并安装 Django。
c:\>cd c:\Django-x.xx
接下来,通过运行以下命令来安装 Django,您需要在 Windows shell“cmd”中拥有管理权限 -
c:\Django-x.xx>python setup.py install
要测试您的安装,请打开命令提示符并键入以下命令 -
c:\>django-admin.py --version
如果您看到屏幕上打印出 Django 的当前版本,则一切都已设置。
或者
启动“cmd”提示符并输入 python,然后 -
c:\> python >>> import django >>> print django.get_version()
第 3 步 – 数据库设置
Django 支持几种主要的数据库引擎,您可以根据自己的喜好设置其中任何一个。
- MySQL (http://www.mysql.com/)
- PostgreSQL (http://www.postgresql.org/)
- SQLite 3 (http://www.sqlite.org/)
- 甲骨文 (http://www.oracle.com/)
- MongoDb (https://django-mongodb-engine.readthedocs.org)
- GoogleAppEngine 数据存储区 (https://cloud.google.com/appengine/articles/django-nonrel)
您可以参考相应的文档来安装和配置您选择的数据库。
注- 5 号和 6 号是 NoSQL 数据库。
第 4 步 – 网络服务器
Django 附带了一个轻量级 Web 服务器,用于开发和测试应用程序。该服务器已预先配置为与 Django 一起使用,更重要的是,每当您修改代码时,它都会重新启动。
但是,Django 确实支持 Apache 和其他流行的 Web 服务器,例如 Lighttpd。我们将在接下来的章节中讨论这两种方法,同时使用不同的示例。
Django - 创建项目
现在我们已经安装了 Django,让我们开始使用它。在 Django 中,您要创建的每个 Web 应用程序都称为项目;项目是应用程序的总和。应用程序是一组依赖于 MVT 模式的代码文件。举个例子,假设我们要建立一个网站,该网站是我们的项目,论坛、新闻、联系引擎是应用程序。这种结构使得在项目之间移动应用程序变得更加容易,因为每个应用程序都是独立的。
创建一个项目
无论您使用的是 Windows 还是 Linux,只需获取终端或cmd提示符并导航到您想要创建项目的位置,然后使用以下代码 -
$ django-admin startproject myproject
这将创建一个具有以下结构的“myproject”文件夹 -
myproject/ manage.py myproject/ __init__.py settings.py urls.py wsgi.py
项目结构
“myproject”文件夹只是您的项目容器,它实际上包含两个元素 -
manage.py - 该文件是您的项目本地 django-admin 的一种,用于通过命令行与您的项目进行交互(启动开发服务器,同步数据库...)。要获取可通过manage.py访问的命令的完整列表,您可以使用以下代码 -
$ python manage.py help
“myproject”子文件夹- 该文件夹是项目的实际 python 包。它包含四个文件 -
__init__.py - 仅对于 python,将此文件夹视为包。
settings.py - 顾名思义,您的项目设置。
urls.py - 项目的所有链接和要调用的函数。项目的一种目录。
wsgi.py - 如果您需要通过 WSGI 部署项目。
设置您的项目
您的项目设置在子文件夹 myproject/settings.py 中。以下是您可能需要设置的一些重要选项 -
DEBUG = True
此选项允许您设置项目是否处于调试模式。调试模式可让您获取有关项目错误的更多信息。对于实时项目,切勿将其设置为“True”。但是,如果您希望 Django 轻型服务器提供静态文件,则必须将其设置为“True”。仅在开发模式下执行此操作。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'database.sql', 'USER': '', 'PASSWORD': '', 'HOST': '', 'PORT': '', } }
数据库在“数据库”字典中设置。上面的例子是针对 SQLite 引擎的。如前所述,Django 还支持 -
- MySQL(django.db.backends.mysql)
- PostGreSQL (django.db.backends.postgresql_psycopg2)
- Oracle (django.db.backends.oracle) 和 NoSQL DB
- MongoDB (django_mongodb_engine)
在设置任何新引擎之前,请确保安装了正确的数据库驱动程序。
您还可以设置其他选项,例如:TIME_ZONE、LANGUAGE_CODE、TEMPLATE...
现在您的项目已创建并配置完毕,请确保它正在运行 -
$ python manage.py runserver
运行上面的代码你会得到类似下面的内容 -
Validating models... 0 errors found September 03, 2015 - 11:41:50 Django version 1.6.11, using settings 'myproject.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
Django - 应用程序生命周期
一个项目是许多应用程序的总和。每个应用程序都有一个目标,并且可以在另一个项目中重用,就像网站上的联系表单可以是一个应用程序,并且可以为其他人重用。将其视为项目的模块。
创建应用程序
我们假设您位于项目文件夹中。在我们的主“myproject”文件夹中,同一个文件夹中还有manage.py -
$ python manage.py startapp myapp
您刚刚创建了 myapp 应用程序,并且像项目一样,Django 创建了一个包含应用程序结构的“myapp”文件夹 -
myapp/ __init__.py admin.py models.py tests.py views.py
__init__.py - 只是为了确保 python 将此文件夹作为包处理。
admin.py - 此文件可帮助您使应用程序在管理界面中可修改。
models.py - 这是存储所有应用程序模型的位置。
test.py - 这是单元测试所在的位置。
views.py - 这是您的应用程序视图所在的位置。
让项目了解您的应用
在这个阶段,我们已经有了“myapp”应用程序,现在我们需要将其注册到我们的 Django 项目“myproject”中。为此,请更新项目的 settings.py 文件中的 INSTALLED_APPS 元组(添加您的应用程序名称) -
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myapp', )
Django - 管理界面
Django 为管理活动提供了一个即用型用户界面。我们都知道管理界面对于网络项目有多重要。Django 根据您的项目模型自动生成管理 UI。
启动管理界面
管理界面依赖于 django.countrib 模块。要使其正常工作,您需要确保在 myproject/settings.py 文件的 INSTALLED_APPS 和 MIDDLEWARE_CLASSES 元组中导入一些模块。
对于 INSTALLED_APPS,请确保您有 -
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myapp', )
对于 MIDDLEWARE_CLASSES -
MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', )
在启动服务器之前,要访问管理界面,您需要启动数据库 -
$ python manage.py migrate
syncdb 将根据您的数据库类型创建必要的表或集合,这是管理界面运行所必需的。即使您没有超级用户,系统也会提示您创建一个。
如果您已经拥有超级用户或忘记了它,您可以随时使用以下代码创建一个超级用户 -
$ python manage.py createsuperuser
现在要启动管理界面,我们需要确保已为管理界面配置了 URL。打开 myproject/url.py 你应该有类似的东西 -
from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', # Examples: # url(r'^$', 'myproject.views.home', name = 'home'), # url(r'^blog/', include('blog.urls')), url(r'^admin/', include(admin.site.urls)), )
现在只需运行服务器即可。
$ python manage.py runserver
您的管理界面可以通过以下地址访问:http://127.0.0.1:8000/admin/
连接到您的超级用户帐户后,您将看到以下屏幕 -
该界面将允许您管理 Django 组和用户,以及应用程序中的所有注册模型。该界面使您至少能够对模型执行“CRUD”(创建、读取、更新、删除)操作。
Django - 创建视图
视图函数(或简称“视图”)只是一个接受 Web 请求并返回 Web 响应的 Python 函数。这个响应可以是网页的HTML内容,或者是重定向,或者是404错误,或者是XML文档,或者是图片等。 示例:你使用视图创建网页,注意需要关联一个视图到 URL 以将其视为网页。
在Django 中,必须在应用程序views.py 文件中创建视图。
简单视图
我们将在 myapp 中创建一个简单的视图来表示“欢迎使用我的应用程序!”
请参阅以下视图 -
from django.http import HttpResponse def hello(request): text = """<h1>welcome to my app !</h1>""" return HttpResponse(text)
在此视图中,我们使用 HttpResponse 来呈现 HTML(您可能已经注意到,我们在视图中硬编码了 HTML)。要将此视图视为页面,我们只需将其映射到 URL(这将在下一章中讨论)。
我们之前使用 HttpResponse 在视图中渲染 HTML。这不是呈现页面的最佳方式。Django 支持 MVT 模式,因此要制作先例视图,像 Django - MVT 一样,我们需要 -
模板:myapp/templates/hello.html
现在我们的视图将如下所示 -
from django.shortcuts import render def hello(request): return render(request, "myapp/template/hello.html", {})
视图还可以接受参数 -
from django.http import HttpResponse def hello(request, number): text = "<h1>welcome to my app number %s!</h1>"% number return HttpResponse(text)
当链接到 URL 时,页面将显示作为参数传递的数字。请注意,参数将通过 URL 传递(在下一章中讨论)。
Django - URL 映射
现在我们已经有了前面章节中所解释的工作视图。我们希望通过 URL 访问该视图。Django 有自己的 URL 映射方式,它是通过编辑项目 url.py 文件(myproject/url.py)来完成的。url.py 文件看起来像 -
from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', #Examples #url(r'^$', 'myproject.view.home', name = 'home'), #url(r'^blog/', include('blog.urls')), url(r'^admin', include(admin.site.urls)), )
当用户对 Web 应用程序上的页面发出请求时,Django 控制器将接管并通过 url.py 文件查找相应的视图,然后返回 HTML 响应,如果未找到,则返回 404 未找到错误。在 url.py 中,最重要的是“urlpatterns”元组。您可以在其中定义 URL 和视图之间的映射。映射是 URL 模式中的元组,例如 -
from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', #Examples #url(r'^$', 'myproject.view.home', name = 'home'), #url(r'^blog/', include('blog.urls')), url(r'^admin', include(admin.site.urls)), url(r'^hello/', 'myapp.views.hello', name = 'hello'), )
标记的行将 URL“/home”映射到 myapp/view.py 文件中创建的 hello 视图。正如您在上面看到的,映射由三个元素组成 -
模式- 与您想要解析和映射的 URL 匹配的正则表达式。所有可以与 python 're' 模块一起使用的东西都符合该模式(当你想通过 url 传递参数时很有用)。
视图的 python 路径- 与导入模块时相同。
名称- 为了执行 URL 反转,您需要使用命名 URL 模式,如上面的示例所示。完成后,只需启动服务器即可通过以下方式访问您的视图:http://127.0.0.1/hello
组织您的 URL
到目前为止,我们已经在“myprojects/url.py”文件中创建了 URL,但是正如前面关于 Django 和创建应用程序所述,最好的一点是能够在不同的项目中重用应用程序。如果您将所有 URL 保存在“projecturl.py”文件中,您可以轻松看出问题所在。因此,最佳实践是为每个应用程序创建一个“url.py”,并将其包含在我们的主项目 url.py 文件中(我们之前包含了管理界面的管理 URL)。
它是如何完成的?
我们需要使用以下代码在 myapp 中创建一个 url.py 文件 -
from django.conf.urls import patterns, include, url urlpatterns = patterns('', url(r'^hello/', 'myapp.views.hello', name = 'hello'),)
然后 myproject/url.py 将更改为以下内容 -
from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', #Examples #url(r'^$', 'myproject.view.home', name = 'home'), #url(r'^blog/', include('blog.urls')), url(r'^admin', include(admin.site.urls)), url(r'^myapp/', include('myapp.urls')), )
我们已包含 myapp 应用程序中的所有 URL。通过“/hello”访问的 home.html 现在是“/myapp/hello”,对于 Web 应用程序来说,这是一个更好、更容易理解的结构。
现在假设我们在 myapp “morning” 中有另一个视图,我们想将其映射到 myapp/url.py 中,然后我们将 myapp/url.py 更改为 -
from django.conf.urls import patterns, include, url urlpatterns = patterns('', url(r'^hello/', 'myapp.views.hello', name = 'hello'), url(r'^morning/', 'myapp.views.morning', name = 'morning'), )
这可以重构为 -
from django.conf.urls import patterns, include, url urlpatterns = patterns('myapp.views', url(r'^hello/', 'hello', name = 'hello'), url(r'^morning/', 'morning', name = 'morning'),)
正如您所看到的,我们现在使用urlpatterns元组的第一个元素。当您想要更改应用程序名称时,这会很有用。
将参数发送到视图
我们现在知道如何映射 URL,如何组织它们,现在让我们看看如何将参数发送到视图。一个经典的示例是文章示例(您希望通过“/articles/article_id”访问文章)。
传递参数是通过使用URL 模式中的正则表达式捕获它们来完成的。如果我们在“myapp/view.py”中有如下视图
from django.shortcuts import render from django.http import HttpResponse def hello(request): return render(request, "hello.html", {}) def viewArticle(request, articleId): text = "Displaying article Number : %s"%articleId return HttpResponse(text)
我们希望将其映射到 myapp/url.py 中,以便我们可以通过“/myapp/article/articleId”访问它,我们需要在“myapp/url.py”中添加以下内容 -
from django.conf.urls import patterns, include, url urlpatterns = patterns('myapp.views', url(r'^hello/', 'hello', name = 'hello'), url(r'^morning/', 'morning', name = 'morning'), url(r'^article/(\d+)/', 'viewArticle', name = 'article'),)
当 Django 看到 url:“/myapp/article/42”时,它会将参数“42”传递给 viewArticle 视图,在浏览器中您应该得到以下结果 -
请注意,参数的顺序在这里很重要。假设我们想要一年中一个月的文章列表,让我们添加一个 viewArticles 视图。我们的 view.py 变成 -
from django.shortcuts import render from django.http import HttpResponse def hello(request): return render(request, "hello.html", {}) def viewArticle(request, articleId): text = "Displaying article Number : %s"%articleId return HttpResponse(text) def viewArticles(request, month, year): text = "Displaying articles of : %s/%s"%(year, month) return HttpResponse(text)
相应的url.py文件将如下所示 -
from django.conf.urls import patterns, include, url urlpatterns = patterns('myapp.views', url(r'^hello/', 'hello', name = 'hello'), url(r'^morning/', 'morning', name = 'morning'), url(r'^article/(\d+)/', 'viewArticle', name = 'article'), url(r'^articles/(\d{2})/(\d{4})', 'viewArticles', name = 'articles'),)
现在,当您转到“/myapp/articles/12/2006/”时,您将得到“显示文章:2006/12”,但如果反转参数,您将不会得到相同的结果。
为了避免这种情况,可以将 URL 参数链接到视图参数。为此,我们的url.py将变成 -
from django.conf.urls import patterns, include, url urlpatterns = patterns('myapp.views', url(r'^hello/', 'hello', name = 'hello'), url(r'^morning/', 'morning', name = 'morning'), url(r'^article/(\d+)/', 'viewArticle', name = 'article'), url(r'^articles/(?P\d{2})/(?P\d{4})', 'viewArticles', name = 'articles'),)
Django - 模板系统
Django 使得分离 python 和 HTML 成为可能,python 放在视图中,HTML 放在模板中。为了链接两者,Django 依赖于渲染函数和 Django 模板语言。
渲染函数
该函数采用三个参数 -
请求- 初始请求。
模板的路径- 这是相对于项目 settings.py 变量中的 TEMPLATE_DIRS 选项的路径。
参数字典- 包含模板中所需的所有变量的字典。可以创建此变量,也可以使用 locals() 传递视图中声明的所有局部变量。
Django 模板语言 (DTL)
Django 的模板引擎提供了一种迷你语言来定义应用程序面向用户的层。
显示变量
变量如下所示:{{variable}}。模板将渲染函数的第三个参数中的变量替换为视图发送的变量。让我们更改 hello.html 以显示今天的日期 -
你好.html
<html> <body> Hello World!!!<p>Today is {{today}}</p> </body> </html>
那么我们的观点将变为 -
def hello(request): today = datetime.datetime.now().date() return render(request, "hello.html", {"today" : today})
访问 URL/myapp/hello 后我们将得到以下输出 -
Hello World!!! Today is Sept. 11, 2015
你可能已经注意到,如果变量不是字符串,Django 将使用 __str__ 方法来显示它;使用相同的原理,您可以像在 Python 中一样访问对象属性。例如:如果我们想显示日期年份,我的变量将是:{{today.year}}。
过滤器
它们帮助您在显示时修改变量。过滤器结构如下所示:{{var|filters}}。
一些例子-
{{string|truncatewords:80}} - 此过滤器将截断字符串,因此您只会看到前 80 个单词。
{{string|lower}} - 将字符串转换为小写。
{{string|escape|linebreaks}} - 转义字符串内容,然后将换行符转换为标签。
您还可以设置变量的默认值。
标签
标签允许您执行以下操作:if 条件、for 循环、模板继承等。
标记如果
就像在 Python 中一样,您可以在模板中使用 if、else 和 elif -
<html> <body> Hello World!!!<p>Today is {{today}}</p> We are {% if today.day == 1 %} the first day of month. {% elif today.day == 30 %} the last day of month. {% else %} I don't know. {%endif%} </body> </html>
在这个新模板中,根据当天的日期,模板将呈现一定的值。
标记为
就像“if”一样,我们有“for”标签,其工作方式与 Python 中完全相同。让我们更改 hello 视图以将列表传输到我们的模板 -
def hello(request): today = datetime.datetime.now().date() daysOfWeek = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] return render(request, "hello.html", {"today" : today, "days_of_week" : daysOfWeek})
使用 {{ for }} 显示该列表的模板 -
<html> <body> Hello World!!!<p>Today is {{today}}</p> We are {% if today.day == 1 %} the first day of month. {% elif today.day == 30 %} the last day of month. {% else %} I don't know. {%endif%} <p> {% for day in days_of_week %} {{day}} </p> {% endfor %} </body> </html>
我们应该得到类似的东西 -
Hello World!!! Today is Sept. 11, 2015 We are I don't know. Mon Tue Wed Thu Fri Sat Sun
块和扩展标签
如果没有模板继承,模板系统就不完整。这意味着当您设计模板时,您应该有一个带有孔的主模板,子模板将根据自己的需要填充这些孔,就像页面可能需要为所选选项卡使用特殊的 CSS 一样。
让我们更改 hello.html 模板以继承 main_template.html。
main_template.html
<html> <head> <title> {% block title %}Page Title{% endblock %} </title> </head> <body> {% block content %} Body content {% endblock %} </body> </html>
你好.html
{% extends "main_template.html" %} {% block title %}My Hello Page{% endblock %} {% block content %} Hello World!!!<p>Today is {{today}}</p> We are {% if today.day == 1 %} the first day of month. {% elif today.day == 30 %} the last day of month. {% else %} I don't know. {%endif%} <p> {% for day in days_of_week %} {{day}} </p> {% endfor %} {% endblock %}
在上面的示例中,在调用 /myapp/hello 时,我们仍然会得到与以前相同的结果,但现在我们依靠 extends 和 block 来重构我们的代码 -
在 main_template.html 中,我们使用标签 block 定义块。标题块将包含页面标题,内容块将包含页面主要内容。在 home.html 中,我们使用 extends 继承自 main_template.html,然后填充上面定义的块(内容和标题)。
评论标签
注释标签有助于将注释定义到模板中,而不是 HTML 注释,它们不会出现在 HTML 页面中。它对于文档或仅注释一行代码很有用。
Django - 模型
模型是表示数据库中的表或集合的类,该类的每个属性都是表或集合的字段。模型在 app/models.py 中定义(在我们的示例中:myapp/models.py)
创建模型
以下是作为示例创建的 Dreamreal 模型 -
from django.db import models class Dreamreal(models.Model): website = models.CharField(max_length = 50) mail = models.CharField(max_length = 50) name = models.CharField(max_length = 50) phonenumber = models.IntegerField() class Meta: db_table = "dreamreal"
每个模型都继承自 django.db.models.Model。
我们的类有 4 个属性(3 个 CharField 和 1 个 Integer),这些属性将是表字段。
具有 db_table 属性的 Meta 类允许我们定义实际的表或集合名称。Django 自动命名表或集合:myapp_modelName。这个类将让您强制将表的名称更改为您喜欢的名称。
django.db.models 中有更多字段类型,您可以在https://docs.djangoproject.com/en/1.5/ref/models/fields/#field-types上了解更多信息
创建模型后,您将需要 Django 来生成实际的数据库 -
$python manage.py syncdb
操作数据(CRUD)
让我们创建一个“crudops”视图来看看如何对模型进行 CRUD 操作。我们的 myapp/views.py 将看起来像 -
myapp/views.py
from myapp.models import Dreamreal from django.http import HttpResponse def crudops(request): #Creating an entry dreamreal = Dreamreal( website = "www.polo.com", mail = "sorex@polo.com", name = "sorex", phonenumber = "002376970" ) dreamreal.save() #Read ALL entries objects = Dreamreal.objects.all() res ='Printing all Dreamreal entries in the DB : <br>' for elt in objects: res += elt.name+"<br>" #Read a specific entry: sorex = Dreamreal.objects.get(name = "sorex") res += 'Printing One entry <br>' res += sorex.name #Delete an entry res += '<br> Deleting an entry <br>' sorex.delete() #Update dreamreal = Dreamreal( website = "www.polo.com", mail = "sorex@polo.com", name = "sorex", phonenumber = "002376970" ) dreamreal.save() res += 'Updating entry<br>' dreamreal = Dreamreal.objects.get(name = 'sorex') dreamreal.name = 'thierry' dreamreal.save() return HttpResponse(res)
其他数据处理
让我们探索可以对模型进行的其他操作。请注意,CRUD 操作是在模型的实例上完成的,现在我们将直接使用代表模型的类。
让我们在myapp/views.py中创建一个“datamanipulation”视图
from myapp.models import Dreamreal from django.http import HttpResponse def datamanipulation(request): res = '' #Filtering data: qs = Dreamreal.objects.filter(name = "paul") res += "Found : %s results<br>"%len(qs) #Ordering results qs = Dreamreal.objects.order_by("name") for elt in qs: res += elt.name + '<br>' return HttpResponse(res)
连接模型
Django ORM 提供了 3 种链接模型的方法 -
我们在这里看到的第一个案例是一对多关系。正如您在上面的示例中所看到的,Dreamreal 公司可以拥有多个在线网站。定义该关系是通过使用 django.db.models.ForeignKey 来完成的 -
myapp/models.py
from django.db import models class Dreamreal(models.Model): website = models.CharField(max_length = 50) mail = models.CharField(max_length = 50) name = models.CharField(max_length = 50) phonenumber = models.IntegerField() online = models.ForeignKey('Online', default = 1) class Meta: db_table = "dreamreal" class Online(models.Model): domain = models.CharField(max_length = 30) class Meta: db_table = "online"
正如您在更新后的 myapp/models.py 中看到的,我们添加了在线模型并将其链接到我们的 Dreamreal 模型。
让我们通过manage.py shell 检查所有这些是如何工作的 -
首先让我们创建一些公司(Dreamreal 条目)以在 Django shell 中进行测试 -
$python manage.py shell >>> from myapp.models import Dreamreal, Online >>> dr1 = Dreamreal() >>> dr1.website = 'company1.com' >>> dr1.name = 'company1' >>> dr1.mail = 'contact@company1' >>> dr1.phonenumber = '12345' >>> dr1.save() >>> dr2 = Dreamreal() >>> dr1.website = 'company2.com' >>> dr2.website = 'company2.com' >>> dr2.name = 'company2' >>> dr2.mail = 'contact@company2' >>> dr2.phonenumber = '56789' >>> dr2.save()
现在一些托管域 -
>>> on1 = Online() >>> on1.company = dr1 >>> on1.domain = "site1.com" >>> on2 = Online() >>> on2.company = dr1 >>> on2.domain = "site2.com" >>> on3 = Online() >>> on3.domain = "site3.com" >>> dr2 = Dreamreal.objects.all()[2] >>> on3.company = dr2 >>> on1.save() >>> on2.save() >>> on3.save()
从在线域访问托管公司的属性(Dreamreal 条目)很简单 -
>>> on1.company.name
如果我们想知道 Dreamreal 中一家公司托管的所有在线域名,我们将使用以下代码 -
>>> dr1.online_set.all()
要获取 QuerySet,请注意我们之前见过的所有操作方法(filter、all、exclusive、order_by...)
您还可以访问链接模型属性以进行过滤操作,假设您想要获取 Dreamreal 名称包含“公司”的所有在线域 -
>>> Online.objects.filter(company__name__contains = 'company'
注意- SQL DB 仅支持这种查询。它不适用于不存在联接并且有两个“_”的非关系数据库。
但这并不是链接模型的唯一方法,您还可以使用 OneToOneField,这种链接可以保证两个对象之间的关系是唯一的。如果我们在上面的示例中使用 OneToOneField,则意味着对于每个 Dreamreal 条目,只能有一个 Online 条目,反之亦然。
最后一个是表之间 (nn) 关系的 ManyToManyField。请注意,这些与基于 SQL 的数据库相关。
Django - 页面重定向
Web 应用程序中出于多种原因需要页面重定向。当发生特定操作时,或者基本上是在发生错误时,您可能希望将用户重定向到另一个页面。例如,当用户登录您的网站时,他通常会被重定向到主页或个人仪表板。在 Django 中,重定向是使用“redirect”方法完成的。
“redirect”方法采用以下参数: 您想要重定向到的 URL(字符串视图名称)。
到目前为止,myapp/views 如下所示 -
def hello(request): today = datetime.datetime.now().date() daysOfWeek = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] return render(request, "hello.html", {"today" : today, "days_of_week" : daysOfWeek}) def viewArticle(request, articleId): """ A view that display an article based on his ID""" text = "Displaying article Number : %s" %articleId return HttpResponse(text) def viewArticles(request, year, month): text = "Displaying articles of : %s/%s"%(year, month) return HttpResponse(text)
让我们将 hello 视图更改为重定向到 djangoproject.com,并将 viewArticle 更改为重定向到我们的内部“/myapp/articles”。为此,myapp/view.py 将更改为 -
from django.shortcuts import render, redirect from django.http import HttpResponse import datetime # Create your views here. def hello(request): today = datetime.datetime.now().date() daysOfWeek = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] return redirect("https://www.djangoproject.com") def viewArticle(request, articleId): """ A view that display an article based on his ID""" text = "Displaying article Number : %s" %articleId return redirect(viewArticles, year = "2045", month = "02") def viewArticles(request, year, month): text = "Displaying articles of : %s/%s"%(year, month) return HttpResponse(text)
在上面的示例中,首先我们从 django.shortcuts 导入了重定向,为了重定向到 Django 官方网站,我们只需将完整的 URL 作为字符串传递给“redirect”方法,对于第二个示例(viewArticle 视图)“redirect”方法将视图名称及其参数作为参数。
访问 /myapp/hello,将显示以下屏幕 -
访问 /myapp/article/42,将显示以下屏幕 -
还可以通过添加 permanent = True 参数来指定“重定向”是临时的还是永久的。用户不会看到任何差异,但这些是搜索引擎在对您的网站进行排名时考虑的详细信息。
还要记住我们在映射 URL 时在 url.py 中定义的“name”参数 -
url(r'^articles/(?P\d{2})/(?P\d{4})/', 'viewArticles', name = 'articles'),
该名称(此处为文章)可以用作“重定向”方法的参数,然后我们的 viewArticle 重定向可以从 -
def viewArticle(request, articleId): """ A view that display an article based on his ID""" text = "Displaying article Number : %s" %articleId return redirect(viewArticles, year = "2045", month = "02")
至-
def viewArticle(request, articleId): """ A view that display an article based on his ID""" text = "Displaying article Number : %s" %articleId return redirect(articles, year = "2045", month = "02")
注意- 还有一个生成 URL 的函数;它的使用方式与重定向相同;“反向”方法(django.core.urlresolvers.reverse)。此函数不返回 HttpResponseRedirect 对象,而只是返回一个字符串,其中包含使用任何传递的参数编译的视图的 URL。
Django - 发送电子邮件
Django 附带了一个现成且易于使用的轻引擎来发送电子邮件。与 Python 类似,您只需要导入 smtplib。在 Django 中,你只需要导入 django.core.mail。要开始发送电子邮件,请编辑项目 settings.py 文件并设置以下选项 -
EMAIL_HOST - smtp 服务器。
EMAIL_HOST_USER - smtp 服务器的登录凭据。
EMAIL_HOST_PASSWORD - smtp 服务器的密码凭据。
EMAIL_PORT - smtp 服务器端口。
EMAIL_USE_TLS 或 _SSL - 如果安全连接则为 True。
发送简单的电子邮件
让我们创建一个“sendSimpleEmail”视图来发送简单的电子邮件。
from django.core.mail import send_mail from django.http import HttpResponse def sendSimpleEmail(request,emailto): res = send_mail("hello paul", "comment tu vas?", "paul@polo.com", [emailto]) return HttpResponse('%s'%res)
这是 send_mail 参数的详细信息 -
主题- 电子邮件主题。
消息- 电子邮件正文。
from_email - 来自的电子邮件。
recipient_list - 接收者的电子邮件地址列表。
failure_silently - Bool,如果 false send_mail 将在发生错误时引发异常。
auth_user - 如果未在 settings.py 中设置,则用户登录。
auth_password - 如果未在 settings.py 中设置,则为用户密码。
连接- 电子邮件后端。
html_message - (Django 1.7 中的新功能)如果存在,电子邮件将是多部分/替代的。
让我们创建一个 URL 来访问我们的视图 -
from django.conf.urls import patterns, url urlpatterns = paterns('myapp.views', url(r'^simpleemail/(?P<emailto> [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/', 'sendSimpleEmail' , name = 'sendSimpleEmail'),)
因此,当访问 /myapp/simpleemail/polo@gmail.com 时,您将看到以下页面 -
使用 send_mass_mail 发送多封邮件
该方法返回成功发送的消息数。这与 send_mail 相同,但需要一个额外的参数;数据元组,我们的 sendMassEmail 视图将是 -
from django.core.mail import send_mass_mail from django.http import HttpResponse def sendMassEmail(request,emailto): msg1 = ('subject 1', 'message 1', 'polo@polo.com', [emailto1]) msg2 = ('subject 2', 'message 2', 'polo@polo.com', [emailto2]) res = send_mass_mail((msg1, msg2), fail_silently = False) return HttpResponse('%s'%res)
让我们创建一个 URL 来访问我们的视图 -
from django.conf.urls import patterns, url urlpatterns = paterns('myapp.views', url(r'^massEmail/(?P<emailto1> [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/(?P<emailto2> [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})', 'sendMassEmail' , name = 'sendMassEmail'),)
访问 /myapp/massemail/polo@gmail.com/sorex@gmail.com/ 时,我们得到 -
send_mass_mail 参数详细信息是 -
数据元组- 每个元素类似于(主题、消息、from_email、recipient_list)的元组。
failure_silently - Bool,如果 false send_mail 将在发生错误时引发异常。
auth_user - 如果未在 settings.py 中设置,则用户登录。
auth_password - 如果未在 settings.py 中设置,则为用户密码。
连接- 电子邮件后端。
如上图所示,两条消息已成功发送。
注意- 在此示例中,我们使用 Python smtp 调试服务器,您可以使用以下命令启动 -
$python -m smtpd -n -c DebuggingServer localhost:1025
这意味着您发送的所有电子邮件都将打印在标准输出上,并且虚拟服务器在 localhost:1025 上运行。
使用 mail_admins 和 mail_managers 方法向管理员和经理发送电子邮件
这些方法将电子邮件发送给在 settings.py 文件的 ADMINS 选项中定义的站点管理员,以及在 settings.py 文件的 MANAGERS 选项中定义的站点管理员。让我们假设我们的 ADMINS 和 MANAGERS 选项如下所示 -
管理员= (('polo', 'polo@polo.com'),)
经理= (('popoli', 'popoli@polo.com'),)
from django.core.mail import mail_admins from django.http import HttpResponse def sendAdminsEmail(request): res = mail_admins('my subject', 'site is going down.') return HttpResponse('%s'%res)
上面的代码将向 ADMINS 部分中定义的每个管理员发送一封电子邮件。
from django.core.mail import mail_managers from django.http import HttpResponse def sendManagersEmail(request): res = mail_managers('my subject 2', 'Change date on the site.') return HttpResponse('%s'%res)
上面的代码将向 MANAGERS 部分中定义的每个经理发送一封电子邮件。
参数详细信息 -
主题- 电子邮件主题。
消息- 电子邮件正文。
failure_silently - Bool,如果 false send_mail 将在发生错误时引发异常。
连接- 电子邮件后端。
html_message - (Django 1.7 中的新功能)如果存在,电子邮件将是多部分/替代的。
发送 HTML 电子邮件
在 Django >= 1.7 中发送 HTML 消息非常简单 -
from django.core.mail import send_mail from django.http import HttpResponse res = send_mail("hello paul", "comment tu vas?", "paul@polo.com", ["polo@gmail.com"], html_message=")
这将生成一封多部分/替代电子邮件。
但对于 Django < 1.7 来说,发送 HTML 消息是通过 django.core.mail.EmailMessage 类完成的,然后在对象上调用“发送” -
让我们创建一个“sendHTMLEmail”视图来发送 HTML 电子邮件。
from django.core.mail import EmailMessage from django.http import HttpResponse def sendHTMLEmail(request , emailto): html_content = "<strong>Comment tu vas?</strong>" email = EmailMessage("my subject", html_content, "paul@polo.com", [emailto]) email.content_subtype = "html" res = email.send() return HttpResponse('%s'%res)
EmailMessage 类创建的参数详细信息 -
主题- 电子邮件主题。
message - HTML 格式的电子邮件正文。
from_email - 来自的电子邮件。
to - 接收者的电子邮件地址列表。
密件抄送- “密件抄送”接收者的电子邮件地址列表。
连接- 电子邮件后端。
让我们创建一个 URL 来访问我们的视图 -
from django.conf.urls import patterns, url urlpatterns = paterns('myapp.views', url(r'^htmlemail/(?P<emailto> [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/', 'sendHTMLEmail' , name = 'sendHTMLEmail'),)
当访问 /myapp/htmlemail/polo@gmail.com 时,我们得到 -
发送带附件的电子邮件
这是通过使用 EmailMessage 对象上的“attach”方法来完成的。
发送带有附件的电子邮件的视图将是 -
from django.core.mail import EmailMessage from django.http import HttpResponse def sendEmailWithAttach(request, emailto): html_content = "Comment tu vas?" email = EmailMessage("my subject", html_content, "paul@polo.com", emailto]) email.content_subtype = "html" fd = open('manage.py', 'r') email.attach('manage.py', fd.read(), 'text/plain') res = email.send() return HttpResponse('%s'%res)
有关附加参数的详细信息 -
filename - 要附加的文件的名称。
content - 要附加的文件的内容。
mimetype - 附件的内容 mime 类型。
Django - 通用视图
在某些情况下,正如我们之前所见,编写视图确实很繁重。想象一下您需要一个静态页面或列表页面。Django 提供了一种简单的方法来设置这些简单视图,称为通用视图。
与经典视图不同,通用视图是类而不是函数。Django 在 django.views.generic 中提供了一组通用视图类,每个通用视图都是这些类中的一个或从其中一个继承的类。
有 10 多个通用类 -
>>> import django.views.generic >>> dir(django.views.generic) ['ArchiveIndexView', 'CreateView', 'DateDetailView', 'DayArchiveView', 'DeleteView', 'DetailView', 'FormView', 'GenericViewError', 'ListView', 'MonthArchiveView', 'RedirectView', 'TemplateView', 'TodayArchiveView', 'UpdateView', 'View', 'WeekArchiveView', 'YearArchiveView', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'base', 'dates', 'detail', 'edit', 'list']
您可以将其用于通用视图。让我们看一些例子来看看它是如何工作的。
静态页面
让我们从“static.html”模板发布一个静态页面。
我们的 static.html -
<html> <body> This is a static page!!! </body> </html>
如果我们按照之前学过的方式这样做,我们就必须将myapp/views.py更改为 -
from django.shortcuts import render def static(request): return render(request, 'static.html', {})
和myapp/urls.py是 -
from django.conf.urls import patterns, url urlpatterns = patterns("myapp.views", url(r'^static/', 'static', name = 'static'),)
最好的方法是使用通用视图。为此,我们的 myapp/views.py 将变成 -
from django.views.generic import TemplateView class StaticView(TemplateView): template_name = "static.html"
我们的 myapp/urls.py 将是 -
from myapp.views import StaticView from django.conf.urls import patterns urlpatterns = patterns("myapp.views", (r'^static/$', StaticView.as_view()),)
当访问 /myapp/static 时,你会得到 -
对于相同的结果,我们也可以执行以下操作 -
- views.py 没有变化
- 将 url.py 文件更改为 -
from django.views.generic import TemplateView from django.conf.urls import patterns, url urlpatterns = patterns("myapp.views", url(r'^static/',TemplateView.as_view(template_name = 'static.html')),)
可以看到,只需要更改第二种方法中的url.py文件即可。
列出并显示数据库中的数据
我们将列出 Dreamreal 模型中的所有条目。通过使用 ListView 通用视图类可以轻松完成此操作。编辑 url.py 文件并将其更新为 -
from django.views.generic import ListView from django.conf.urls import patterns, url urlpatterns = patterns( "myapp.views", url(r'^dreamreals/', ListView.as_view(model = Dreamreal, template_name = "dreamreal_list.html")), )
此时需要注意的是,通用视图传递给模板的变量是object_list。如果您想自己命名,则需要向 as_view 方法添加 context_object_name 参数。然后 url.py 将变成 -
from django.views.generic import ListView from django.conf.urls import patterns, url urlpatterns = patterns("myapp.views", url(r'^dreamreals/', ListView.as_view( template_name = "dreamreal_list.html")), model = Dreamreal, context_object_name = ”dreamreals_objects” ,)
关联的模板将是 -
{% extends "main_template.html" %} {% block content %} Dreamreals:<p> {% for dr in object_list %} {{dr.name}}</p> {% endfor %} {% endblock %}
访问 /myapp/dreamreals/ 将产生以下页面 -
Django - 表单处理
在 Django 中创建表单与创建模型非常相似。同样,我们只需要继承 Django 类,类属性将是表单字段。让我们在 myapp 文件夹中添加一个forms.py文件来包含我们的应用程序表单。我们将创建一个登录表单。
myapp/forms.py
#-*- coding: utf-8 -*- from django import forms class LoginForm(forms.Form): user = forms.CharField(max_length = 100) password = forms.CharField(widget = forms.PasswordInput())
如上所示,字段类型可以采用“widget”参数进行 html 渲染;在我们的例子中,我们希望隐藏而不是显示密码。Django 中还存在许多其他小部件:用于日期的DateInput 、用于复选框的CheckboxInput等。
在视图中使用表单
HTTP 请求有两种:GET 和 POST。在 Django 中,作为参数传递给视图的请求对象有一个名为“method”的属性,其中设置了请求的类型,并且可以通过 request.POST 字典访问通过 POST 传递的所有数据。
让我们在 myapp/views.py 中创建一个登录视图 -
#-*- coding: utf-8 -*- from myapp.forms import LoginForm def login(request): username = "not logged in" if request.method == "POST": #Get the posted form MyLoginForm = LoginForm(request.POST) if MyLoginForm.is_valid(): username = MyLoginForm.cleaned_data['username'] else: MyLoginForm = Loginform() return render(request, 'loggedin.html', {"username" : username})
该视图将显示通过loggedin.html发布的登录表单的结果。为了测试它,我们首先需要登录表单模板。我们将其命名为login.html。
<html> <body> <form name = "form" action = "{% url "myapp.views.login" %}" method = "POST" >{% csrf_token %} <div style = "max-width:470px;"> <center> <input type = "text" style = "margin-left:20%;" placeholder = "Identifiant" name = "username" /> </center> </div> <br> <div style = "max-width:470px;"> <center> <input type = "password" style = "margin-left:20%;" placeholder = "password" name = "password" /> </center> </div> <br> <div style = "max-width:470px;"> <center> <button style = "border:0px; background-color:#4285F4; margin-top:8%; height:35px; width:80%;margin-left:19%;" type = "submit" value = "Login" > <strong>Login</strong> </button> </center> </div> </form> </body> </html>
该模板将显示一个登录表单并将结果发布到上面的登录视图。您可能已经注意到模板中的标签,这只是为了防止您网站上的跨站请求伪造(CSRF)攻击。
{% csrf_token %}
一旦我们有了登录模板,我们就需要在表单处理后呈现的login.html 模板。
<html> <body> You are : <strong>{{username}}</strong> </body> </html>
现在,我们只需要一对 URL 即可开始:myapp/urls.py
from django.conf.urls import patterns, url from django.views.generic import TemplateView urlpatterns = patterns('myapp.views', url(r'^connection/',TemplateView.as_view(template_name = 'login.html')), url(r'^login/', 'login', name = 'login'))
当访问“/myapp/connection”时,我们将得到以下呈现的login.html模板 -
在表格帖子上,表格有效。在我们的例子中,请确保填写这两个字段,您将得到 -
如果您的用户名是 polo,并且您忘记了密码。您将收到以下消息 -
使用我们自己的表单验证
在上面的示例中,验证表单时 -
MyLoginForm.is_valid()
我们只使用 Django 自表单验证引擎,在我们的例子中只是确保字段是必填的。现在让我们尝试确保尝试登录的用户作为 Dreamreal 条目出现在我们的数据库中。为此,将 myapp/forms.py 更改为 -