Django 快速指南



Django - 基础

Django 是一个高级 Python Web 框架,它鼓励快速开发和简洁、实用的设计。Django 使构建更好的 Web 应用更加容易,速度更快,代码更少。

注意 − Django 是 Django 软件基金会的注册商标,并根据 BSD 许可证授权。

Django 的历史

  • 2003 − 由 Adrian Holovaty 和 Simon Willison 在 Lawrence Journal-World 报社启动的一个内部项目。

  • 2005 − 2005 年 7 月发布,并以爵士吉他手 Django Reinhardt 的名字命名。

  • 2005 − 足够成熟,可以处理多个高流量站点。

  • 现在 − Django 现在是一个开源项目,拥有来自世界各地的贡献者。

Django – 设计理念

Django 具有以下设计理念:

  • 松散耦合 − Django 旨在使其堆栈的每个元素彼此独立。

  • 代码更少 − 更少的代码,从而实现快速开发。

  • 不要重复自己 (DRY) − 每一件事都应该只在一个地方开发,而不是一遍遍重复。

  • 快速开发 − Django 的理念是尽其所能促进超快速开发。

  • 简洁的设计 − Django 严格地在自己的代码中保持简洁的设计,并使其易于遵循最佳 Web 开发实践。

Django 的优势

以下是使用 Django 的一些优势:

  • 对象关系映射 (ORM) 支持 − Django 在数据模型和数据库引擎之间架起了一座桥梁,并支持大量数据库系统,包括 MySQL、Oracle、Postgres 等。Django 还通过 Django-nonrel 分支支持 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 模式的各个组件如何相互交互以响应用户请求:

DJANGO MVC - MVT Pattern

开发人员提供模型、视图和模板,然后将其映射到 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

否则,您可以从链接https://www.pythonlang.cn/downloads/下载并安装最新版本的 Python。

步骤 2 - 安装 Django

安装 Django 非常容易,但安装所需的步骤取决于您的操作系统。由于 Python 是一种平台无关的语言,因此 Django 有一个可在任何地方使用的软件包,无论您的操作系统是什么。

您可以从链接https://django.ac.cn/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 支持多种主要的数据库引擎,您可以根据自己的喜好设置其中任何一个。

您可以参考相应的文档来安装和配置您选择的数据库。

注意 − 5 和 6 是 NoSQL 数据库。

步骤 4 – Web 服务器

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': '',
   }
}

数据库在“Database”字典中设置。上面的示例是针对 SQLite 引擎的。如前所述,Django 还支持:

  • MySQL (django.db.backends.mysql)
  • PostGreSQL (django.db.backends.postgresql_psycopg2)
  • Oracle (django.db.backends.oracle) 和 NoSQL 数据库
  • 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 − 这是存储所有应用程序模型的地方。

  • tests.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提供了一个现成的用户界面,用于执行管理活动。我们都知道管理界面对于Web项目的重要性。Django会根据您的项目模型自动生成管理UI。

启动管理界面

管理界面依赖于`django.contrib`模块。要使其正常工作,您需要确保在`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/urls.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/

Admin Interface

使用超级用户帐户连接后,您将看到以下屏幕:

Super User Account

该界面允许您管理Django组和用户,以及应用程序中所有已注册的模型。该界面至少允许您对模型执行“CRUD”(创建、读取、更新、删除)操作。

Django - 创建视图

视图函数(简称“视图”)只是一个Python函数,它接收一个Web请求并返回一个Web响应。此响应可以是网页的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映射方式,这是通过编辑项目`urls.py`文件**(myproject/urls.py)**来完成的。`urls.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控制器接管以通过`urls.py`文件查找相应的视图,然后返回HTML响应或404未找到错误(如果未找到)。在`urls.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/views.py`文件中创建的`hello`视图。如上所示,映射由三个元素组成:

  • 模式 − 与您想要解析和映射的URL匹配的正则表达式。Python 're' 模块可以使用的任何内容都符合模式的条件(当您想通过URL传递参数时很有用)。

  • 视图的Python路径 − 与导入模块时相同。

  • 名称 − 为了执行URL反转,您需要使用上面示例中所示的命名URL模式。完成后,只需启动服务器即可通过:http://127.0.0.1/hello访问您的视图。

组织您的URL

到目前为止,我们已在“myprojects/urls.py”文件中创建了URL,但是如前所述,关于Django和创建应用程序的最佳之处在于能够在不同的项目中重用应用程序。如果您将所有URL都保存在“projecturls.py”文件中,那么很容易看出问题所在。因此,最佳实践是为每个应用程序创建一个“urls.py”,并将其包含在我们的主要项目urls.py文件中(我们之前包含了管理界面的admin URLs)。

Organize URLs

如何操作?

我们需要使用以下代码在myapp中创建一个urls.py文件:

from django.conf.urls import patterns, include, url

urlpatterns = patterns('', url(r'^hello/', 'myapp.views.hello', name = 'hello'),)

然后`myproject/urls.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。“home.html”之前通过“/hello”访问,现在是“/myapp/hello”,这是Web应用程序更好、更容易理解的结构。

Myproject

现在假设我们在myapp中还有另一个视图“morning”,并且我们想在`myapp/urls.py`中映射它,那么我们将更改`myapp/urls.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 Patterns

向视图发送参数

我们现在知道如何映射URL,如何组织它们,现在让我们看看如何向视图发送参数。一个经典的示例是文章示例(您想通过“/articles/article_id”访问一篇文章)。

传递参数是通过在URL模式中使用**正则表达式**捕获它们来完成的。如果我们在“myapp/views.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/urls.py`中映射它,以便我们可以通过“/myapp/article/articleId”访问它,我们需要在“myapp/urls.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`视图,在您的浏览器中,您应该得到以下结果:

Passing parameters to viewArticle

请注意,此处参数的顺序很重要。假设我们想要一年中一个月的文章列表,让我们添加一个`viewArticles`视图。我们的`views.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)

相应的**urls.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/”时,您将得到'Displaying articles of: 2006/12',但如果您反转参数,您将不会得到相同的结果。

Displaying Articles

为避免这种情况,可以将URL参数链接到视图参数。为此,我们的**urls.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依赖于render函数和Django模板语言。

Render函数

此函数接受三个参数:

  • 请求 − 初始请求。

  • 模板路径 − 这是相对于项目`settings.py`变量中的`TEMPLATE_DIRS`选项的相对路径。

  • 参数字典 − 包含模板中所需所有变量的字典。可以创建此变量,也可以使用`locals()`传递在视图中声明的所有局部变量。

Django模板语言 (DTL)

Django的模板引擎提供了一种小型语言来定义应用程序的用户界面层。

显示变量

变量如下所示:{{variable}}。模板会将变量替换为视图在render函数的第三个参数中发送的变量。让我们更改`hello.html`以显示今天的日期:

hello.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循环、模板继承等等。

if标签

就像在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>

在这个新的模板中,根据一天中的日期,模板将渲染某个值。

for标签

就像'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

Block和Extend标签

如果没有模板继承,模板系统就不完整。这意味着在设计模板时,您应该有一个带有空洞的主模板,子模板将根据其自身的需求填充这些空洞,例如页面可能需要为选定的选项卡使用特殊的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>

hello.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` 标签定义块。`title` 块将包含页面标题,`content` 块将包含页面主要内容。在 `home.html` 中,我们使用 `extends` 继承 `main_template.html`,然后填充上面定义的块(`content` 和 `title`)。

注释标签

注释标签用于在模板中定义注释,而不是 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 个 `IntegerField`),这些将成为表字段。

`Meta` 类带有 `db_table` 属性,允许我们定义实际的表或集合名称。Django 会自动命名表或集合:`myapp_modelName`。此类将允许您强制将表名设置为您喜欢的名称。

创建模型后,您需要 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 = "[email protected]", 
      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 = "[email protected]", 
      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 提供了三种关联模型的方法:

我们将在这里看到的第一个案例是一对多关系。正如你在上面的例子中看到的,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` 中看到的,我们添加了 `online` 模型并将其与我们的 `Dreamreal` 模型关联。

让我们通过 `manage.py shell` 检查这一切是如何工作的:

首先,让我们在 Django shell 中创建一些公司(Dreamreal 条目)进行测试:

$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`、`exclude`、`order_by`……)。

您还可以访问关联模型属性进行过滤操作,例如,您想获取 Dreamreal 名称包含“company”的所有在线域名:

>>> Online.objects.filter(company__name__contains = 'company'

**注意** - 此类查询仅支持 SQL 数据库。它不适用于不存在连接且有两个下划线的非关系数据库。

但这并不是关联模型的唯一方法,您还可以使用 `OneToOneField`,这是一种保证两个对象之间的关系唯一的关联。如果我们在上面的示例中使用 `OneToOneField`,则意味着对于每个 Dreamreal 条目,只有一个 Online 条目是可能的,反之亦然。

最后一个是 `ManyToManyField`,用于表之间的 (n-n) 关系。请注意,这些与基于 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://django.ac.cn")
	
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` 导入 `redirect`,对于重定向到 Django 官方网站,我们只需将完整的 URL 作为字符串传递给 'redirect' 方法,对于第二个例子(viewArticle 视图),'redirect' 方法将视图名称及其参数作为参数。

访问 /myapp/hello,将显示以下屏幕:

Django page Redirection Example1

访问 /myapp/article/42,将显示以下屏幕:

Django page Redirection Example2

还可以通过添加 `permanent = True` 参数来指定重定向是临时的还是永久的。用户不会看到任何区别,但这对于搜索引擎在对您的网站进行排名时考虑的细节。

还要记住我们在映射 URL 时在 `url.py` 中定义的 'name' 参数:

url(r'^articles/(?P\d{2})/(?P\d{4})/', 'viewArticles', name = 'articles'),

该名称(此处为 article)可以用作 'redirect' 方法的参数,然后我们的 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;它与 redirect 的使用方法相同;'reverse' 方法(`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?", "[email protected]", [emailto])
   return HttpResponse('%s'%res)

以下是 `send_mail` 参数的详细信息:

  • **`subject`** - 电子邮件主题。

  • **`message`** - 电子邮件正文。

  • **`from_email`** - 发件人邮箱。

  • **`recipient_list`** - 收件人邮箱地址列表。

  • **`fail_silently`** - 布尔值,如果为 false,则 `send_mail` 将在发生错误时引发异常。

  • **`auth_user`** - 如果未在 `settings.py` 中设置,则为用户登录名。

  • **`auth_password`** - 如果未在 `settings.py` 中设置,则为用户密码。

  • **`connection`** - 电子邮件后端。

  • **`html_message`** - (Django 1.7 中的新增功能)如果存在,电子邮件将是 multipart/alternative。

让我们创建一个 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/[email protected] 时,您将看到以下页面:

Sending Simple E-mail

使用 `send_mass_mail` 发送多封邮件

该方法返回成功发送的消息数量。这与 `send_mail` 相同,但需要一个额外的参数;`datatuple`,我们的 `sendMassEmail` 视图将如下所示:

from django.core.mail import send_mass_mail
from django.http import HttpResponse

def sendMassEmail(request,emailto):
   msg1 = ('subject 1', 'message 1', '[email protected]', [emailto1])
   msg2 = ('subject 2', 'message 2', '[email protected]', [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/[email protected]/[email protected]/ 时,我们将得到:

Sending Multiple Mails

`send_mass_mail` 参数详细信息:

  • **`datatuples`** - 一个元组,其中每个元素都像 (subject, message, from_email, recipient_list)。

  • **`fail_silently`** - 布尔值,如果为 false,则 `send_mail` 将在发生错误时引发异常。

  • **`auth_user`** - 如果未在 `settings.py` 中设置,则为用户登录名。

  • **`auth_password`** - 如果未在 `settings.py` 中设置,则为用户密码。

  • **`connection`** - 电子邮件后端。

正如你在上图中看到的,两封邮件已成功发送。

**注意** - 在此示例中,我们使用的是 Python smtp 调试服务器,您可以使用以下命令启动:

$python -m smtpd -n -c DebuggingServer localhost:1025

这意味着您发送的所有电子邮件都将打印在标准输出上,并且虚拟服务器正在 localhost:1025 上运行。

使用 `mail_admins` 和 `mail_managers` 方法向管理员和管理人员发送电子邮件

这些方法将电子邮件发送给 `settings.py` 文件的 `ADMINS` 选项中定义的站点管理员,以及 `settings.py` 文件的 `MANAGERS` 选项中定义的站点管理员。让我们假设我们的 `ADMINS` 和 `MANAGERS` 选项如下所示:

**`ADMINS`** = (('polo', '[email protected]'),)

**`MANAGERS`** = (('popoli', '[email protected]'),)

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` 部分中定义的每个管理员发送一封电子邮件。

参数详情:

  • **`Subject`** - 电子邮件主题。

  • **`message`** - 电子邮件正文。

  • **`fail_silently`** - 布尔值,如果为 false,则 `send_mail` 将在发生错误时引发异常。

  • **`connection`** - 电子邮件后端。

  • **`html_message`** - (Django 1.7 中的新增功能)如果存在,电子邮件将是 multipart/alternative。

发送 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?", "[email protected]", 
         ["[email protected]"], html_message=")

这将生成一个 multipart/alternative 电子邮件。

但是对于 Django < 1.7,发送 HTML 消息是通过 `django.core.mail.EmailMessage` 类完成的,然后在对象上调用 'send':

让我们创建一个 "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, "[email protected]", [emailto])
   email.content_subtype = "html"
   res = email.send()
   return HttpResponse('%s'%res)

`EmailMessage` 类创建的参数详细信息:

  • **`Subject`** - 电子邮件主题。

  • **`message`** - HTML 格式的电子邮件正文。

  • **`from_email`** - 发件人邮箱。

  • **`to`** - 收件人邮箱地址列表。

  • **`bcc`** - “Bcc” 收件人邮箱地址列表。

  • **`connection`** - 电子邮件后端。

让我们创建一个 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/[email protected] 时,我们将得到:

Sending HTML E-mail

发送带有附件的电子邮件

这是通过在 `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, "[email protected]", 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)

`attach` 参数的详细信息:

  • **`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时,您将获得:

Static Page

为了得到相同的结果,我们也可以执行以下操作:

  • 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/将生成以下页面:

List and Display Data from DB

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中还有许多其他widget:用于日期的**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 %}

拥有登录模板后,我们需要在表单处理后呈现的loggedin.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模板:

Login HTML Template

在表单提交后,表单有效。在我们的例子中,确保填写这两个字段,您将得到:

Form Validation

如果您的用户名是polo,并且您忘记了密码。您将收到以下消息:

Form Invalid Message

使用我们自己的表单验证

在上面的例子中,验证表单时:

MyLoginForm.is_valid()

我们只使用了Django自身的表单验证引擎,在我们的例子中只是确保字段是必需的。现在让我们确保尝试登录的用户存在于我们的数据库中作为Dreamreal条目。为此,将myapp/forms.py更改为:

#-*- coding: utf-8 -*-
from django import forms
from myapp.models import Dreamreal

class LoginForm(forms.Form):
   user = forms.CharField(max_length = 100)
   password = forms.CharField(widget = forms.PasswordInput())

   def clean_message(self):
      username = self.cleaned_data.get("username")
      dbuser = Dreamreal.objects.filter(name = username)
      
      if not dbuser:
         raise forms.ValidationError("User does not exist in our db!")
      return username

现在,在调用“is_valid”方法后,只有当用户在我们的数据库中时,我们才能获得正确的输出。如果您想检查表单的字段,只需在表单类中添加一个以“clean_”开头的方法,然后是您的字段名称。引发forms.ValidationError非常重要。

Django - 文件上传

对于 Web 应用来说,能够上传文件(个人资料图片、歌曲、pdf、文档……)通常很有用。本章将讨论如何上传文件。

上传图像

在开始使用图像之前,请确保已安装 Python 图像库 (PIL)。现在,为了说明如何上传图像,让我们在我们的myapp/forms.py中创建一个个人资料表单:

#-*- coding: utf-8 -*-
from django import forms

class ProfileForm(forms.Form):
   name = forms.CharField(max_length = 100)
   picture = forms.ImageFields()

如您所见,这里的主要区别只是**forms.ImageField**。ImageField 将确保上传的文件是图像。如果不是,则表单验证将失败。

现在让我们创建一个“Profile”模型来保存我们上传的个人资料。这在myapp/models.py中完成:

from django.db import models

class Profile(models.Model):
   name = models.CharField(max_length = 50)
   picture = models.ImageField(upload_to = 'pictures')

   class Meta:
      db_table = "profile"

如您所见,对于模型,ImageField 需要一个强制性参数:**upload_to**。这表示将在硬盘驱动器上保存图像的位置。请注意,该参数将添加到您的settings.py文件中定义的MEDIA_ROOT选项中。

现在我们有了表单和模型,让我们在myapp/views.py中创建视图:

#-*- coding: utf-8 -*-
from myapp.forms import ProfileForm
from myapp.models import Profile

def SaveProfile(request):
   saved = False
   
   if request.method == "POST":
      #Get the posted form
      MyProfileForm = ProfileForm(request.POST, request.FILES)
      
      if MyProfileForm.is_valid():
         profile = Profile()
         profile.name = MyProfileForm.cleaned_data["name"]
         profile.picture = MyProfileForm.cleaned_data["picture"]
         profile.save()
         saved = True
   else:
      MyProfileForm = Profileform()
		
   return render(request, 'saved.html', locals())

需要注意的部分是,创建ProfileForm时有一个变化,我们添加了第二个参数:**request.FILES**。如果没有传递,表单验证将失败,并显示图片为空的消息。

现在,我们只需要**saved.html**模板和**profile.html**模板,用于表单和重定向页面:

**myapp/templates/saved.html**:

<html>
   <body>
   
      {% if saved %}
         <strong>Your profile was saved.</strong>
      {% endif %}
      
      {% if not saved %}
         <strong>Your profile was not saved.</strong>
      {% endif %}
      
   </body>
</html>

**myapp/templates/profile.html**:

<html>
   <body>
   
      <form name = "form" enctype = "multipart/form-data" 
         action = "{% url "myapp.views.SaveProfile" %}" method = "POST" >{% csrf_token %}
         
         <div style = "max-width:470px;">
            <center>  
               <input type = "text" style = "margin-left:20%;" 
               placeholder = "Name" name = "name" />
            </center>
         </div>
			
         <br>
         
         <div style = "max-width:470px;">
            <center> 
               <input type = "file" style = "margin-left:20%;" 
                  placeholder = "Picture" name = "picture" />
            </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>

接下来,我们需要我们的URL对才能开始:myapp/urls.py

from django.conf.urls import patterns, url
from django.views.generic import TemplateView

urlpatterns = patterns(
   'myapp.views', url(r'^profile/',TemplateView.as_view(
      template_name = 'profile.html')), url(r'^saved/', 'SaveProfile', name = 'saved')
)

访问“/myapp/profile”时,我们将获得呈现的以下profile.html模板:

Uploading Image

在表单提交后,将呈现saved模板:

Form Post Template

我们有一个图像示例,但是如果您想上传其他类型的文件,而不仅仅是图像,只需将模型和表单中的**ImageField**替换为**FileField**。

Django - Apache 配置

到目前为止,在我们的示例中,我们使用了Django开发Web服务器。但是这个服务器只是用于测试,不适合生产环境。投入生产后,您需要一个真正的服务器,例如Apache、Nginx等。本章将讨论Apache。

通过Apache提供Django应用程序是通过使用mod_wsgi完成的。因此,首先要确保已安装Apache和mod_wsgi。请记住,当我们创建项目并查看项目结构时,它看起来像:

myproject/
   manage.py
   myproject/
      __init__.py
      settings.py
      urls.py
      wsgi.py

wsgi.py文件负责处理Django和Apache之间的链接。

假设我们要与Apache共享我们的项目(myproject)。我们只需要设置Apache来访问我们的文件夹。假设我们将myproject文件夹放在默认的“/var/www/html”中。在这个阶段,访问项目将通过127.0.0.1/myproject完成。这将导致Apache只列出文件夹,如下面的快照所示。

Django Apache Setup

如您所见,Apache没有处理Django内容。为了解决这个问题,我们需要在httpd.conf中配置Apache。因此,打开httpd.conf并添加以下行:

WSGIScriptAlias / /var/www/html/myproject/myproject/wsgi.py
WSGIPythonPath /var/www/html/myproject/

<Directory /var/www/html/myproject/>
   <Files wsgi.py>
      Order deny,allow
      Allow from all
   </Files>
</Directory>

如果您能以127.0.0.1/myapp/connection访问登录页面,您将看到以下页面:

Login Page

Django - Cookie 处理

有时,您可能希望根据 Web 应用程序的要求,按每个站点访问者的基础存储一些数据。始终记住,cookie 存储在客户端,并且取决于客户端浏览器的安全级别,设置 cookie 有时有效,有时可能无效。

为了说明在Django中处理cookie,让我们创建一个使用我们之前创建的登录系统的系统。该系统将让您登录X分钟的时间,超过该时间,您将退出应用程序。

为此,您需要设置两个cookie,last_connection和username。

首先,让我们更改登录视图以存储我们的用户名和last_connection cookie:

from django.template import RequestContext

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()
   
   response = render_to_response(request, 'loggedin.html', {"username" : username}, 
      context_instance = RequestContext(request))
   
   response.set_cookie('last_connection', datetime.datetime.now())
   response.set_cookie('username', datetime.datetime.now())
	
   return response

如上图所示,设置cookie是通过对响应而不是请求调用的**set_cookie**方法完成的,并且请注意所有cookie值都作为字符串返回。

现在让我们为登录表单创建一个formView,如果设置了cookie并且cookie不超过10秒,我们将不显示表单:

def formView(request):
   if 'username' in request.COOKIES and 'last_connection' in request.COOKIES:
      username = request.COOKIES['username']
      
      last_connection = request.COOKIES['last_connection']
      last_connection_time = datetime.datetime.strptime(last_connection[:-7], 
         "%Y-%m-%d %H:%M:%S")
      
      if (datetime.datetime.now() - last_connection_time).seconds < 10:
         return render(request, 'loggedin.html', {"username" : username})
      else:
         return render(request, 'login.html', {})
			
   else:
      return render(request, 'login.html', {})

如上所示的formView中,访问您设置的cookie是通过请求的COOKIES属性(字典)完成的。

现在让我们更改url.py文件以更改URL,使其与我们的新视图配对:

from django.conf.urls import patterns, url
from django.views.generic import TemplateView

urlpatterns = patterns('myapp.views',
   url(r'^connection/','formView', name = 'loginform'),
   url(r'^login/', 'login', name = 'login'))

访问/myapp/connection时,您将看到以下页面:

Django Cookies Handling

提交后,您将被重定向到以下屏幕:

Cookies Handling Redirected Page

现在,如果您尝试在10秒范围内再次访问/myapp/connection,您将直接被重定向到第二个屏幕。如果您在此范围之外再次访问/myapp/connection,您将获得登录表单(屏幕1)。

Django - Session

如前所述,我们可以使用客户端cookie来存储许多对Web应用程序有用的数据。我们之前已经看到,我们可以使用客户端cookie来存储对我们的Web应用程序有用的各种数据。这会导致许多安全漏洞,具体取决于您要保存的数据的重要性。

出于安全原因,Django有一个用于处理cookie的会话框架。会话用于抽象接收和发送cookie,数据保存在服务器端(例如在数据库中),客户端cookie只有一个会话ID用于标识。会话也有助于避免用户浏览器设置为“不接受”cookie的情况。

设置会话

在Django中,启用会话是在您的项目**settings.py**中完成的,方法是向**MIDDLEWARE_CLASSES**和**INSTALLED_APPS**选项添加一些行。这应该在创建项目时完成,但了解这一点总是好的,因此**MIDDLEWARE_CLASSES**应该具有:

'django.contrib.sessions.middleware.SessionMiddleware'

而**INSTALLED_APPS**应该具有:

'django.contrib.sessions'

默认情况下,Django将会话信息保存在数据库中(django_session表或集合),但您可以配置引擎以使用其他方式存储信息,例如:在**文件**中或在**缓存**中。

启用会话后,每个请求(Django中任何视图的第一个参数)都具有一个session(字典)属性。

让我们创建一个简单的示例,看看如何创建和保存会话。我们之前构建了一个简单的登录系统(请参阅Django表单处理章节和Django Cookie处理章节)。让我们将用户名保存在cookie中,因此,如果没有注销,当访问我们的登录页面时,您将看不到登录表单。基本上,让我们使我们在Django Cookie处理中使用的登录系统更安全,方法是将cookie保存在服务器端。

为此,首先让我们更改登录视图以将用户名cookie保存在服务器端:

def login(request):
   username = 'not logged in'
   
   if request.method == 'POST':
      MyLoginForm = LoginForm(request.POST)
      
      if MyLoginForm.is_valid():
         username = MyLoginForm.cleaned_data['username']
         request.session['username'] = username
      else:
         MyLoginForm = LoginForm()
			
   return render(request, 'loggedin.html', {"username" : username}

然后让我们为登录表单创建formView视图,如果设置了cookie,我们将不显示表单:

def formView(request):
   if request.session.has_key('username'):
      username = request.session['username']
      return render(request, 'loggedin.html', {"username" : username})
   else:
      return render(request, 'login.html', {})

现在让我们更改url.py文件以更改URL,使其与我们的新视图配对:

from django.conf.urls import patterns, url
from django.views.generic import TemplateView

urlpatterns = patterns('myapp.views',
   url(r'^connection/','formView', name = 'loginform'),
   url(r'^login/', 'login', name = 'login'))

访问/myapp/connection时,您将看到以下页面:

Setting Up Sessions

您将被重定向到以下页面:

Sessions Redirected Page

现在,如果您尝试再次访问/myapp/connection,您将直接被重定向到第二个屏幕。

让我们创建一个简单的注销视图来删除我们的cookie。

def logout(request):
   try:
      del request.session['username']
   except:
      pass
   return HttpResponse("<strong>You are logged out.</strong>")

并将其与myapp/url.py中的注销URL配对

url(r'^logout/', 'logout', name = 'logout'),

现在,如果您访问/myapp/logout,您将看到以下页面:

Logged Out Page

如果您再次访问/myapp/connection,您将获得登录表单(屏幕1)。

使用会话可以执行的更多可能的动作

我们已经学习了如何存储和访问会话,但了解请求的会话属性还有一些其他有用的操作也很重要:

  • set_expiry (value) − 设置会话的过期时间。

  • get_expiry_age() − 返回此会话过期前的秒数。

  • get_expiry_date() − 返回此会话将过期的日期。

  • clear_expired() − 从会话存储中删除过期的会话。

  • get_expire_at_browser_close() − 返回 True 或 False,取决于用户关闭浏览器时用户会话 cookie 是否已过期。

Django - 缓存

缓存是指保存昂贵计算的结果,以便在下次需要时无需再次执行。下面是一个伪代码,解释了缓存的工作原理:

given a URL, try finding that page in the cache

if the page is in the cache:
   return the cached page
else:
   generate the page
   save the generated page in the cache (for next time)
   return the generated page

Django 自带自己的缓存系统,允许您保存动态页面,避免在需要时再次计算它们。Django 缓存框架的优点在于您可以缓存:

  • 特定视图的输出。
  • 模板的一部分。
  • 您的整个站点。

要在 Django 中使用缓存,首先需要设置缓存的存储位置。缓存框架提供了不同的可能性——缓存可以保存在数据库中、文件系统中或直接保存在内存中。设置是在项目的 settings.py 文件中完成的。

在数据库中设置缓存

只需在项目 settings.py 文件中添加以下内容:

CACHES = {
   'default': {
      'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
      'LOCATION': 'my_table_name',
   }
}

为了使此设置生效并完成设置,我们需要创建缓存表“my_table_name”。为此,您需要执行以下操作:

python manage.py createcachetable

在文件系统中设置缓存

只需在项目 settings.py 文件中添加以下内容:

CACHES = {
   'default': {
      'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
      'LOCATION': '/var/tmp/django_cache',
   }
}

在内存中设置缓存

这是最有效的缓存方式,您可以根据为内存缓存选择的 Python 绑定库使用以下选项之一:

CACHES = {
   'default': {
      'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
      'LOCATION': '127.0.0.1:11211',
   }
}

或者

CACHES = {
   'default': {
      'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
      'LOCATION': 'unix:/tmp/memcached.sock',
   }
}

缓存整个站点

在 Django 中使用缓存最简单的方法是缓存整个站点。这是通过编辑项目 settings.py 中的 MIDDLEWARE_CLASSES 选项来完成的。需要向该选项添加以下内容:

MIDDLEWARE_CLASSES += (
   'django.middleware.cache.UpdateCacheMiddleware',
   'django.middleware.common.CommonMiddleware',
   'django.middleware.cache.FetchFromCacheMiddleware',
)

请注意,这里的顺序很重要,Update 应该在 Fetch 中间件之前。

然后在同一个文件中,您需要设置:

CACHE_MIDDLEWARE_ALIAS – The cache alias to use for storage.
CACHE_MIDDLEWARE_SECONDS – The number of seconds each page should be cached.

缓存视图

如果您不想缓存整个站点,您可以缓存特定的视图。这是通过使用 Django 自带的 cache_page 装饰器来完成的。假设我们要缓存 viewArticles 视图的结果:

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)

def viewArticles(request, year, month):
   text = "Displaying articles of : %s/%s"%(year, month)
   return HttpResponse(text)

如您所见,cache_page 将视图结果缓存的秒数作为参数。在上面的示例中,结果将缓存 15 分钟。

注意 − 正如我们之前看到的,上面的视图映射到:

urlpatterns = patterns('myapp.views',
   url(r'^articles/(?P<month>\d{2})/(?P<year>\d{4})/', 'viewArticles', name = 'articles'),)

由于 URL 正在获取参数,因此每个不同的调用都将单独缓存。例如,对 /myapp/articles/02/2007 的请求将与对 /myapp/articles/03/2008 的请求分别缓存。

也可以直接在 url.py 文件中缓存视图。然后,以下内容与上述内容具有相同的结果。只需编辑您的 myapp/url.py 文件并更改相关的映射 URL(如上)为:

urlpatterns = patterns('myapp.views',
   url(r'^articles/(?P<month>\d{2})/(?P<year>\d{4})/', 
   cache_page(60 * 15)('viewArticles'), name = 'articles'),)

当然,myapp/views.py 中不再需要它了。

缓存模板片段

您还可以缓存模板的一部分,这是通过使用 cache 标签来完成的。让我们以我们的 hello.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 %}

为了缓存内容块,我们的模板将变为:

{% load cache %}
{% extends "main_template.html" %}
{% block title %}My Hello Page{% endblock %}
{% cache 500 content %}
{% 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 %}
{% endcache %}

如您在上面看到的,cache 标签将接受两个参数:要缓存块的时间(以秒为单位)和要赋予缓存片段的名称。

Django - 评论

在开始之前,请注意,Django 评论框架自 1.5 版本起已弃用。现在您可以使用外部功能来实现此目的,但如果您仍然想要使用它,它仍然包含在 1.6 和 1.7 版本中。从 1.8 版本开始,它不存在,但您仍然可以在不同的 GitHub 帐户上获取代码。

评论框架使您可以轻松地将评论附加到应用程序中的任何模型。

要开始使用 Django 评论框架:

编辑项目 settings.py 文件,并将 'django.contrib.sites''django.contrib.comments' 添加到 INSTALLED_APPS 选项:

INSTALLED_APPS += ('django.contrib.sites', 'django.contrib.comments',)

获取站点 ID:

>>> from django.contrib.sites.models import Site
>>> Site().save()
>>> Site.objects.all()[0].id
u'56194498e13823167dd43c64'

在 settings.py 文件中设置您获得的 ID:

SITE_ID = u'56194498e13823167dd43c64'

同步数据库,以创建所有评论表或集合:

python manage.py syncdb

将评论应用程序的 URL 添加到项目的 urls.py:

from django.conf.urls import include
url(r'^comments/', include('django.contrib.comments.urls')),

现在我们已经安装了框架,让我们更改 hello 模板以跟踪我们 Dreamreal 模型上的评论。我们将列出并保存特定 Dreamreal 条目的评论,其名称将作为参数传递给 /myapp/hello URL。

Dreamreal 模型

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"

hello 视图

def hello(request, Name):
   today = datetime.datetime.now().date()
   daysOfWeek = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
   dreamreal = Dreamreal.objects.get(name = Name)
   return render(request, 'hello.html', locals())

hello.html 模板

{% extends "main_template.html" %}
{% load comments %}
{% block title %}My Hello Page{% endblock %}
{% block content %}

<p>
   Our Dreamreal Entry:
   <p><strong>Name :</strong> {{dreamreal.name}}</p>
   <p><strong>Website :</strong> {{dreamreal.website}}</p>
   <p><strong>Phone :</strong> {{dreamreal.phonenumber}}</p>
   <p><strong>Number of comments :<strong> 
   {% get_comment_count for dreamreal as comment_count %} {{ comment_count }}</p>
   <p>List of comments :</p>
   {% render_comment_list for dreamreal %}
</p>

{% render_comment_form for dreamreal %}
{% endblock %}

最后是 hello 视图的映射 URL:

url(r'^hello/(?P<Name>\w+)/', 'hello', name = 'hello'),

现在,

  • 在我们的模板 (hello.html) 中,使用 {% load comments %} 加载评论框架。

  • 我们获取视图传递的 Dreamreal 对象的评论数量:{% get_comment_count for dreamreal as comment_count %}

  • 我们获取对象的评论列表:{% render_comment_list for dreamreal %}

  • 我们显示默认的评论表单:{% render_comment_form for dreamreal %}

访问 /myapp/hello/steve 时,您将获得名称为 Steve 的 Dreamreal 条目的评论信息。访问该 URL 将获得:

Django Comments Example

发布评论后,您将被重定向到以下页面:

Comments Redirected Page

如果您再次访问 /myapp/hello/steve,您将看到以下页面:

Number of Comments

如您所见,评论数量现在为 1,并且您在评论列表行下有评论。

Django - RSS

Django 带有一个联合供稿生成框架。使用它,您可以通过子类化 django.contrib.syndication.views.Feed 类 来创建 RSS 或 Atom 供稿。

让我们为应用程序上最新的评论创建一个供稿(另请参见 Django - 评论框架章节)。为此,让我们创建一个 myapp/feeds.py 并定义我们的供稿(您可以将供稿类放在代码结构中的任何位置)。

from django.contrib.syndication.views import Feed
from django.contrib.comments import Comment
from django.core.urlresolvers import reverse

class DreamrealCommentsFeed(Feed):
   title = "Dreamreal's comments"
   link = "/drcomments/"
   description = "Updates on new comments on Dreamreal entry."

   def items(self):
      return Comment.objects.all().order_by("-submit_date")[:5]
		
   def item_title(self, item):
      return item.user_name
		
   def item_description(self, item):
      return item.comment
		
   def item_link(self, item):
      return reverse('comment', kwargs = {'object_pk':item.pk})
  • 在我们的供稿类中,titlelinkdescription 属性对应于标准 RSS <title><link><description> 元素。

  • items 方法返回应作为项目元素添加到供稿中的元素。在本例中,是最近五条评论。

  • item_title 方法将获取作为供稿项目标题的内容。在本例中,标题将是用户名。

  • item_description 方法将获取作为供稿项目描述的内容。在本例中,是评论本身。

  • item_link 方法将构建指向完整项目的链接。在本例中,它将引导您到评论。

现在我们有了供稿,让我们在 views.py 中添加一个评论视图来显示我们的评论:

from django.contrib.comments import Comment

def comment(request, object_pk):
   mycomment = Comment.objects.get(object_pk = object_pk)
   text = '<strong>User :</strong> %s <p>'%mycomment.user_name</p>
   text += '<strong>Comment :</strong> %s <p>'%mycomment.comment</p>
   return HttpResponse(text)

我们还需要在 myapp urls.py 中添加一些 URL 用于映射:

from myapp.feeds import DreamrealCommentsFeed
from django.conf.urls import patterns, url

urlpatterns += patterns('',
   url(r'^latest/comments/', DreamrealCommentsFeed()),
   url(r'^comment/(?P\w+)/', 'comment', name = 'comment'),
)

访问 /myapp/latest/comments/ 时,您将获得我们的供稿:

Django RSS Example

然后单击其中一个用户名将转到:/myapp/comment/comment_id(如我们之前的评论视图中定义),您将获得:

Django RSS Redirected Page

因此,定义 RSS 供稿只是子类化 Feed 类并确保定义了 URL(一个用于访问供稿,一个用于访问供稿元素)的问题。就像评论一样,这可以附加到应用程序中的任何模型。

Django - Ajax

Ajax 本质上是集成在一起以减少页面加载次数的技术组合。我们通常使用 Ajax 来简化最终用户体验。在 Django 中使用 Ajax 可以通过直接使用 Ajax 库(如 JQuery 或其他库)来完成。假设您想使用 JQuery,那么您需要下载并通过 Apache 或其他服务器在您的服务器上提供该库。然后像开发任何基于 Ajax 的应用程序一样在您的模板中使用它。

在 Django 中使用 Ajax 的另一种方法是使用 Django Ajax 框架。最常用的框架是 django-dajax,它是一个强大的工具,可以使用 Python 和几乎没有 JavaScript 源代码轻松快速地在 Web 应用程序中开发异步表示逻辑。它支持四个最流行的 Ajax 框架:Prototype、jQuery、Dojo 和 MooTools。

使用 Django-dajax

首先需要安装 django-dajax。这可以使用 easy_install 或 pip 来完成:

$ pip install django_dajax
$ easy_install django_dajax

这将自动安装 django-dajaxice(django-dajax 需要)。然后我们需要配置 dajax 和 dajaxice。

在项目 settings.py 中的 INSTALLED_APPS 选项中添加 dajax 和 dajaxice:

INSTALLED_APPS += (
   'dajaxice',
   'dajax'
)

确保在同一个 settings.py 文件中,您具有以下内容:

TEMPLATE_LOADERS = (
   'django.template.loaders.filesystem.Loader',
   'django.template.loaders.app_directories.Loader',
   'django.template.loaders.eggs.Loader',
)

TEMPLATE_CONTEXT_PROCESSORS = (
   'django.contrib.auth.context_processors.auth',
   'django.core.context_processors.debug',
   'django.core.context_processors.i18n',
   'django.core.context_processors.media',
   'django.core.context_processors.static',
   'django.core.context_processors.request',
   'django.contrib.messages.context_processors.messages'
)

STATICFILES_FINDERS = (
   'django.contrib.staticfiles.finders.FileSystemFinder',
   'django.contrib.staticfiles.finders.AppDirectoriesFinder',
   'dajaxice.finders.DajaxiceFinder',
)

DAJAXICE_MEDIA_PREFIX = 'dajaxice'

现在转到 myapp/url.py 文件,确保您具有以下内容以设置 dajax URL 并加载 dajax statics js 文件:

from dajaxice.core import dajaxice_autodiscover, dajaxice_config
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf import settings

Then dajax urls:

urlpatterns += patterns('',
   url(r'^%s/' % settings.DAJAXICE_MEDIA_PREFIX, include('dajaxice.urls')),)
	
urlpatterns += staticfiles_urlpatterns()

让我们创建一个基于我们的 Dreamreal 模型的简单表单来使用 Ajax 存储它(意味着无需刷新)。

首先,我们需要在 myapp/form.py 中的 Dreamreal 表单。

class DreamrealForm(forms.Form):
   website = forms.CharField(max_length = 100)
   name = forms.CharField(max_length = 100)
   phonenumber = forms.CharField(max_length = 50)
   email = forms.CharField(max_length = 100)

然后我们需要在我们的应用程序中创建一个 ajax.py 文件:myapp/ajax.py。这就是我们的逻辑所在,这就是我们放置保存表单然后返回弹出窗口的函数的地方:

from dajaxice.utils import deserialize_form
from myapp.form import DreamrealForm
from dajax.core import Dajax
from myapp.models import Dreamreal

@dajaxice_register
def send_form(request, form):
   dajax = Dajax()
   form = DreamrealForm(deserialize_form(form))
   
   if form.is_valid():
      dajax.remove_css_class('#my_form input', 'error')
      dr = Dreamreal()
      dr.website = form.cleaned_data.get('website')
      dr.name = form.cleaned_data.get('name')
      dr.phonenumber = form.cleaned_data.get('phonenumber')
      dr.save()
      
      dajax.alert("Dreamreal Entry %s was successfully saved." % 
         form.cleaned_data.get('name'))
   else:
      dajax.remove_css_class('#my_form input', 'error')
      for error in form.errors:
         dajax.add_css_class('#id_%s' % error, 'error')
			
   return dajax.json()

现在让我们创建 dreamreal.html 模板,其中包含我们的表单:

<html>
   <head></head>
   <body>
   
      <form action = "" method = "post" id = "my_form" accept-charset = "utf-8">
         {{ form.as_p }}
         <p><input type = "button" value = "Send" onclick = "send_form();"></p>
      </form>
      
   </body>
</html>

在 myapp/views.py 中添加与模板一起使用的视图:

def dreamreal(request):
   form = DreamrealForm()
   return render(request, 'dreamreal.html', locals())

在 myapp/urls.py 中添加相应的 URL:

url(r'^dreamreal/', 'dreamreal', name = 'dreamreal'),

现在让我们在模板中添加必要的代码以使 Ajax 工作:

在文件顶部添加:

{% load static %}
{% load dajaxice_templatetags %}

并在 dreamreal.html 模板的 <head> 部分添加:

在此示例中,我们使用的是 JQuery 库,因此添加:

<script src = "{% static '/static/jquery-1.11.3.min.js' %}" 
   type = "text/javascript" charset = "utf-8"></script>
<script src = "{% static '/static/dajax/jquery.dajax.core.js' %}"></script>

单击时将调用的 Ajax 函数:

<script>

   function send_form(){
      Dajaxice.myapp.send_form(Dajax.process,{'form':$('#my_form').serialize(true)});
   }
</script>

请注意,您需要在静态文件目录中使用“jquery-1.11.3.min.js”,以及 jquery.dajax.core.js。要确保所有 dajax 静态文件都在您的静态目录下提供服务,请运行:

$python manage.py collectstatic

注意 − 有时 jquery.dajax.core.js 可能丢失,如果发生这种情况,只需下载源代码并获取该文件并将其放入您的静态文件夹中。

访问 /myapp/dreamreal/ 时,您将看到以下屏幕:

Using Django-dajax

提交后,您将看到以下屏幕:

Using Django-dajax Response
广告