Django 简明教程

Django - Quick Guide

Django - Basics

Django 是一个高级 Python Web 框架,它鼓励快速开发以及干净、实用设计。借助 Django,您可以更快、用更少的代码构建更好的 Web 应用程序。

Note − Django 是 Django 软件基金会的注册商标,并根据 BSD 许可证获得许可。

History of Django

  1. 2003 − 最初由 Adrian Holovaty 和 Simon Willison 在 Lawrence Journal-World 报刊社作为一个内部项目开始。

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

  3. 2005 − 足够成熟,可以处理几个高流量站点。

  4. Current − Django 现在是一个开放源代码项目,有来自世界各地的贡献者。

Django – Design Philosophies

Django 有以下设计理念 −

  1. Loosely Coupled − Django 的目标是让其堆栈中的每个元素独立于其他元素。

  2. Less Coding − 减少代码量,从而加快开发速度。

  3. Don’t Repeat Yourself (DRY) − 所有内容都应该只在完全一个的地方开发,而不是反复重复开发。

  4. Fast Development − Django 的理念是在尽其所能的基础上促进超快速开发。

  5. Clean Design −Django 在其自己的代码中严格保持一个简洁的设计,并且让易于遵循最佳 Web 开发实践。

Advantages of Django

以下是使用 Django 的一些优势,在此处列出 −

  1. Object-Relational Mapping (ORM) Support − Django 提供了数据模型与数据库引擎之间的桥梁,并支持大量的数据库系统,包括 MySQL、Oracle、Postgres 等。Django 还通过 Django-nonrel fork 支持 NoSQL 数据库。目前,唯一支持的 NoSQL 数据库是 MongoDB 和 google app engine。

  2. Multilingual Support − Django 通过其内置的国际化系统支持多语言网站。因此,您可以开发支持多种语言的网站。

  3. Framework Support − Django 内置支持 Ajax、RSS、缓存和各种其他框架。

  4. Administration GUI − Django 为管理活动提供了一个好用的、可直接使用的用户界面。

  5. Development Environment − Django 配备了一个轻量级 Web 服务器,以便于端到端应用程序开发和测试。

Django - Overview

正如您所知,Django 是一个 Python Web 框架。与大多数现代框架一样,Django 支持 MVC 模式。我们先来看看模型-视图-控制器 (MVC) 模式是什么,然后我们再来看看 Django 对模型-视图-模板 (MVT) 模式的特殊性。

MVC Pattern

当谈论提供 UI(Web 或桌面)的应用程序时,我们通常会讨论 MVC 架构。顾名思义,MVC 模式基于三个组件:模型、视图和控制器。{s2} 了解更多信息。

DJANGO MVC - MVT Pattern

模型-视图-模板 (MVT) 与 MVC 稍有不同。事实上,这两种模式之间的主要区别在于 Django 本身负责控制器部分(控制模型和视图之间交互的软件代码),而我们保留了模板。模板是一个混合了 Django 模板语言 (DTL) 的 HTML 文件。

下图说明了 MVT 模式的每个组件如何协同交互来响应用户请求 -

django mvc mvt pattern

开发人员提供模型、视图和模板,然后将其映射到网址,Django 展现魔力提供给用户。

Django - Environment

Django 开发环境包括安装和设置 Python、Django 和数据库系统。由于 Django 涉及到 Web 应用程序,因此值得一提的是,你还需要设置一个 Web 服务器。

Step 1 – Installing 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。

Step 2 - Installing Django

安装 Django 非常容易,但所需的安装步骤取决于你的操作系统。由于 Python 是一个平台无关的语言,因此 Django 有适用于所有操作系统的通用软件包。

你可以从 http://www.djangoproject.com/download 链接中下载最新版本的 Django。

UNIX/Linux and Mac OS X Installation

如果你运行的是 Linux 或 Mac OS 系统,则有两种安装 Django 的方法——

  1. 你可以使用操作系统的软件包管理器,或者在已经安装了 easy_install 或 pip 的情况下,可以使用 easy_install 或 pip。

  2. 可以使用之前下载的官方归档文件手动进行安装。

我们将介绍第二种方案,因为第一种方案取决于你的操作系统发行版。如果你决定按照第一种方案进行操作,请小心你安装的 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 版本,则表明一切就绪。

Note - 对于某些版本的 Django,它将是 django-admin,其中的“.py”被删除。

Windows Installation

我们假设你的电脑上已经安装了 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()

Step 3 – Database Setup

Django 支持多个主要的数据库引擎,您可以根据自己的习惯来设置其中的任何一个。

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

Note − 5 号和 6 号是 NoSQL 数据库。

Step 4 – Web Server

Django 带有一个用于开发和测试应用程序的轻量级 Web 服务器。此服务器预配置为与 Django 配合使用,更重要的是,每当您修改代码时都会重新启动。

然而,Django 的确支持 Apache 和其他流行的 Web 服务器,例如 Lighttpd。我们将在处理不同示例时在后续章节中讨论这两种方法。

Django - Creating a Project

既然我们已经安装了 Django,我们开始使用它。在 Django 中,你想要创建的每个 Web 应用程序都被称为一个项目;而一个项目是应用程序的总和。应用程序是依赖于 MVT 模式的一组代码文件。举个例子,假设我们要构建一个网站,网站是我们的项目,论坛、新闻、联系引擎是应用程序。这种结构使得在项目之间移动应用程序变得更容易,因为每个应用程序都是独立的。

Create a Project

无论你在 Windows 还是 Linux 上,只需打开一个终端或一个 cmd 提示符,然后导航到想要创建项目的位置,然后使用以下代码 −

$ django-admin startproject myproject

这将创建一个具有以下结构的 “myproject” 文件夹 −

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

The Project Structure

“myproject” 文件夹只是你的项目容器,它实际上包含两个元素 −

  1. manage.py − 该文件就像你的项目本地 django-admin,可通过命令行与你的项目进行交互(启动开发服务器、同步数据库……)。要获得可通过 manage.py 访问的完整命令列表,可以使用以下代码 −

$ python manage.py help
  1. The “myproject” subfolder − 该文件夹是你的项目的实际 python 包。它包含四个文件 − init.py − 只对 python,将该文件夹视为包。 settings.py − 如名称所示,你的项目设置。 urls.py − 你的项目的所有链接和要调用的函数。有点像你项目的目录。 wsgi.py − 如果你需要通过 WSGI 部署你的项目。

Setting Up Your Project

你的项目在子文件夹 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 还支持 −

  1. MySQL (django.db.backends.mysql)

  2. PostGreSQL (django.db.backends.postgresql_psycopg2)

  3. Oracle (django.db.backends.oracle) 和 NoSQL DB

  4. MongoDB (django_mongodb_engine)

在设置任何新引擎之前,请确保你安装了正确的数据库驱动程序。

你还可以设置其他选项,例如:TIME_ZONELANGUAGE_CODETEMPLATE……

现在你的项目已经创建并配置,确保它正常工作 −

$ 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 - Apps Life Cycle

项目是许多应用程序的总和。每个应用程序都有一个目标,可以重复使用到其他项目中,例如网站上的联系表单可以是一个应用程序,可以重复使用到其他网站。将其视为您项目的模块。

Create an Application

我们假设您在您的项目文件夹中。在我们的主“myproject”文件夹中,然后管理。py -

$ python manage.py startapp myapp

您刚刚创建了 myapp 应用程序,和项目一样,Django 使用应用程序结构创建一个“myapp”文件夹 -

myapp/
   __init__.py
   admin.py
   models.py
   tests.py
   views.py
  1. init.py - 确保 Python 将此文件夹视为一个软件包。

  2. admin.py - 此文件可帮助您在管理员界面中修改应用程序。

  3. models.py - 这是所有应用程序模型的存储位置。

  4. tests.py - 这是您的单元测试所在的位置。

  5. views.py - 这是您的应用程序视图所在的位置。

Get the Project to Know About Your Application

在此阶段,我们有了“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 - Admin Interface

Django 为管理活动提供了一个即用型的用户界面。我们都知道管理界面对于 Web 项目有多么重要。Django 根据您的项目模型自动生成管理用户界面。

Starting the Admin Interface

管理界面依赖于 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

您的管理界面可以在 [role="bare"] [role="bare"]http://127.0.0.1:8000/admin/ 访问:

admin interface

一旦使用超级用户帐户连接,您将看到以下屏幕 −

super user account

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

Django - Creating Views

视图函数,简称“视图”,只是接受 Web 请求并返回 Web 响应的 Python 函数。此响应可以是网页的 HTML 内容,或者重定向,或者 404 错误,或者 XML 文档,或者图像等。示例:你使用视图创建网页,请注意你需要将视图与 URL 关联起来,才能将其视为网页。

在 Django 中,必须在应用程序 views.py 文件中创建视图。

Simple View

我们将在 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 Mapping

现在,我们有了上一章中解释的一个正在工作的视图。我们希望通过一个 URL 访问该视图。Django 有自己的 URL 映射方式,这是通过编辑项目 (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 视图。正如您在上面看到的那样,一个映射由三个元素组成 -

  1. The pattern - 匹配要解析和映射的 URL 的正则表达式。任何可以使用 python“re”模块的内容都符合该模式(在要通过 url 传递参数时很有用)。

  2. The python path to the view - 与导入模块时相同。

  3. The name - 为了执行 URL 反转,您需要像上述示例中那样使用命名的 URL 模式。完成后,只需启动服务器即可通过 :http://127.0.0.1/hello 访问您的视图

Organizing Your URLs

到目前为止,我们已在“myprojects/url.py”文件中创建了 URL,但是如前所述,关于 Django 和创建应用程序,最好的办法是能够在不同的项目中重复使用应用程序。如果您将所有 URL 都保存在“projecturl.py”文件中,您可以轻松地了解问题所在。因此,最佳做法是为每个应用程序创建一个“url.py”,并将其包含在我们的主项目 url.py 文件中(我们之前已包含管理界面用的管理 URL)。

organize urls

How is it Done?

我们需要使用以下代码在 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 应用程序结构。

myproject

现在,假设我们在 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 元组的第一个元素。当您想更改应用程序名称时,这可能很有用。

urlpatterns

Sending Parameters to Views

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

通过在 URL 模式中使用 regexp 捕获参数来传递参数。如果我们在“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 视图,你应该在浏览器中看到以下结果 -

passing parameters to 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/” 时,你会得到 'Displaying articles of: 2006/12',但如果你颠倒了参数的顺序,你将无法得到相同的结果。

displaying articles

为了避免这种情况,可以将一个 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 - Template System

Django 使得可以将 Python 和 HTML 分开,Python 用于视图,HTML 用于模板。为了将两者关联,Django 依靠 render 函数和 Django 模板语言。

The Render Function

此函数需要三个参数 −

  1. Request − 初始请求。

  2. The path to the template − 这是 project settings.py 变量中 TEMPLATE_DIRS 选项的相对路径。

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

Django Template Language (DTL)

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

Displaying Variables

变量看起来像这样:{{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 }}。

Filters

它们帮助您在显示时间修改变量。过滤器结构如下所示:{{ var|filters }}。

Some examples

  1. {{string|truncatewords:80}} − 该过滤器将截断字符串,因此您将只看到前 80 个单词。

  2. {{string|lower}} − 将字符串转换为小写。

  3. {{string|escape|linebreaks}} − 转义字符串内容,然后将换行符转换为标签。

您还可以设置变量的默认值。

Tags

标签允许您执行以下操作:if 条件、for 循环、模板继承等。

Tag 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>

在此新模板中,根据日期,模板将呈现特定值。

Tag 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 and Extend Tags

如果没有模板继承,模板系统将无法完成。也就是说,在设计模板时,应该有一个带有孔的主模板,子模板将根据其需要进行填充,就像一个页面可能需要一个特殊 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 继承,然后我们填充上述定义的块(内容和标题)。

Comment Tag

标签 comment 有助于在模板中定义注释,而不是 HTML 注释,它们不会显示在 HTML 页面中。它可以用来记录文档或仅仅注释一行代码。

Django - Models

模型是一个代表我们 DB 中的表或集合的类,其中类的每个属性都是表或集合的字段。模型在 app/models.py 中定义(在我们的示例中:myapp/models.py)

Creating a Model

以下是作为示例创建的一个 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 来生成实际数据库 −

$python manage.py syncdb

Manipulating Data (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)

Other Data Manipulation

我们探索其他可以在模型上执行的操作。请注意,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)

Linking Models

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 中看到的,我们添加了 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'

Note − 这种类型的查询只受 SQL DB 支持。它不适用于不存在连接符且有两个 _ 的非关系型数据库。

但这不是链接模型的唯一方式,你也有 OneToOneField,一个保证两个对象之间关系唯一性的链接。如果我们在线示例中使用了 OneToOneField,这意味着对于每个 Dreamreal 条目,只有一个 Online 条目是可能的,反之亦然。

最后,有 ManyToManyField 用于表之间的 (n-n) 关系。请注意,这些与基于 SQL 的数据库有关。

Django - Page Redirection

在网络应用程序中,页面重定向有诸多原因。当操作发生或者出错时,你可能希望将用户重定向到其他页面。例如,当用户登录到你的网站时,他经常被定向到主页或者他的个人信息中心。在 Django 中,重定向使用“重定向”方法实现。

“重定向”方法采用以下参数:您希望重定向到的网址字符串。视图名称。

到目前为止,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 导入 redirect,为了重定向到 Django 官方网站,我们只需将完整的网址作为字符串传递给“重定向”方法,对于第二个示例(viewArticle 视图,“重定向”方法采用视图名称和参数作为参数。

访问 /myapp/hello,会看到以下屏幕 -

django page redirection example1

访问 /myapp/article/42,会看到以下屏幕 -

django page redirection example2

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

在映射网址时还能记得到 url.py 中定义的“名称”参数 -

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

该名称(此处为 article)可以用作“重定向”方法的参数,然后我们的 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")

{s0} -

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")

{s1} - 还有一个函数来生成网址;它的用法与 redirect 相同;“反向”方法 (django.core.urlresolvers.reverse)。此方法不会返回 HttpResponseRedirect 对象,而只会返回一个包含与任何传递的参数一起编译的视图网址的字符串。

Django - Sending E-mails

Django 带有一个使用方便的电子邮件发送引擎。与 Python 类似,您需要导入 smtplib。在 Django 中,您只需导入 django.core.mail。若要开始发送电子邮件,请编辑您的项目 settings.py 文件并设置以下选项 −

  1. EMAIL_HOST − smtp server.

  2. EMAIL_HOST_USER − smtp 服务器的登录证书。

  3. EMAIL_HOST_PASSWORD − smtp 服务器的密码证书。

  4. EMAIL_PORT − smtp 服务器端口。

  5. EMAIL_USE_TLS or _SSL − 如果连接安全,则为 True。

Sending a Simple E-mail

让我们创建一个 "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 参数的详细信息 −

  1. subject − E-mail subject.

  2. message − E-mail body.

  3. from_email − E-mail from.

  4. recipient_list − 收件人电子邮件地址列表。

  5. fail_silently − 布尔值,如果为 False,则 send_mail 将在发生错误时引发异常。

  6. auth_user − 如果未在 settings.py 中设置,则为用户登录名。

  7. auth_password − 如果未在 settings.py 中设置,则为用户密码。

  8. connection − E-mail backend.

  9. 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/polo@gmail.com 时,您将获得以下页面 −

sending simple email

Sending Multiple Mails with 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', '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/ 时,我们会得到 −

sending multiple mails

send_mass_mail 参数详细信息 −

  1. datatuples − 一个元组,其中每个元素类似于 (主题、邮件、发件人电子邮件、收件人列表)。

  2. fail_silently − 布尔值,如果为 False,则 send_mail 将在发生错误时引发异常。

  3. auth_user − 如果未在 settings.py 中设置,则为用户登录名。

  4. auth_password − 如果未在 settings.py 中设置,则为用户密码。

  5. connection − E-mail backend.

如上面的图片中可以看到,两封邮件发送成功。

Note − 在这个范例中,我们使用 Python smtp 调试服务器,可使用以下方法启动:

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

这意味着您发送的所有电子邮件都将打印在 stdout 上,而虚拟服务器在 localhost:1025 上运行。

Sending e-mails to admins and managers using mail_admins and mail_managers methods

这些方法向设置文件 settings.py 的 ADMINS 选项中定义的网站管理员和 MANAGERS 选项中定义的网站管理者发送电子邮件。我们假设 ADMINS 和 MANAGERS 选项如下所示:

ADMINS = (('polo', ' polo@polo.com '),)

MANAGERS = (('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 部分中定义的每位管理者发送一封电子邮件。

参数详细信息 −

  1. Subject − E-mail subject.

  2. message − E-mail body.

  3. fail_silently − 布尔值,如果为 False,则 send_mail 将在发生错误时引发异常。

  4. connection − E-mail backend.

  5. html_message −(Django 1.7 中的新增内容)如果存在,电子邮件将是 multipart/alternative。

Sending HTML E-mail

在 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=")

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

但是,在 Django < 1.7 中,要通过使用 django.core.mail.EmailMessage 类向对象调用“send”来发送 HTML 邮件 −

让我们创建一个“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 类创建的参数详细信息 −

  1. Subject − E-mail subject.

  2. message − 以 HTML 表示的电子邮件正文。

  3. from_email − E-mail from.

  4. to − 收件人的电子邮件地址列表。

  5. bcc − “密件抄送”收件人的电子邮件地址列表。

  6. connection − E-mail backend.

让我们创建一个 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 时,会得到 −

sending html email

Sending E-mail with Attachment

这是通过在 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)

附加参数的详情:

  1. filename - 要附加的文件的名称。

  2. content - 要附加的文件的内容。

  3. mimetype - 附件的内容 MIMEType。

Django - Generic Views

在某些情况下,编写视图(如前面看到的那样)确实很繁琐。想象您需要一个静态页面或列表页面。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 Pages

让我们从“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

对于相同的结果,我们还可以执行以下操作:

  1. views.py 中没有任何更改

  2. 将 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 文件。

List and Display Data from DB

我们将列出 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 display data from db

Django - Form Processing

在 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 用于复选框等。

Using Form in a View

有两种 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”时,我们将获得以下登录.html 模板渲染 −

login html template

在表单发布时,表单有效。在我们的案例中,确保填写这两个字段,您将得到 −

form validation

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

form invalid message

Using Our Own Form Validation

在以上示例中,在验证表单时 −

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

现在,在调用 “isValid” 方法之后,只有当用户在我们的数据库中时,我们才会获得正确的结果。如果你想检查表单中的某个字段,只需添加一个以 “clean_” 开头的方法,然后将你的字段名称添加到你的表单类中。提升 forms.ValidationError 非常重要。

Django - File Uploading

web 应用程序通常需要能够上传文件(个人资料图片、歌曲、pdf、文字……)。让我们在本章讨论如何在上传文件。

Uploading an Image

在开始使用图像前,请确保你已安装了 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 将确保上传的文件是图像。如果不是,表单验证将失败。

现在,我们创建一个“个人资料”模型来保存我们上传的个人资料。这在 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

在发布表单时,将渲染已保存的模板 −

form post template

我们有一个图像示例,但是,如果你想上传其他类型的文件,而不仅仅是图片,只需在 Model 和 Form 中用 FileField 替换 ImageField

Django - Apache Setup

到目前为止,在我们的示例中,我们使用了 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 - Cookies Handling

有时候,你可能希望根据 Web 应用程序的要求按每个网站访问者的基础存储一些数据。始终记住,Cookie 存储在客户端,并且根据客户端浏览器安全级别,设置 Cookie 有时会起作用,有时可能不会。

为了说明 Django 中的 Cookie 处理,让我们使用之前创建的登录系统创建一个系统。该系统会让你继续登录 X 分钟,在此时间之后,你将退出应用。

为此,你需要设置两个 Cookie,即 last_connection 和 username。

首先,让我们更改我们的登录视图来存储我们的 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 设置且不早于 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 中所示,你可以通过请求的 COOKIES 属性(dict)来访问设置的 Cookie。

现在,让我们更改 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 - Sessions

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

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

Setting Up Sessions

在 Django 中,会话启用在你的项目 settings.py 中完成,通过向 MIDDLEWARE_CLASSESINSTALLED_APPS 选项添加几行。这应该在创建项目时完成,但了解它总是好的,所以 MIDDLEWARE_CLASSES 应有:

'django.contrib.sessions.middleware.SessionMiddleware'

INSTALLED_APPS 应有:

'django.contrib.sessions'

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

当会话启用时,每个请求(Django 中任何视图的第一个参数)都会有一个会话(dict)属性。

我们创建一个简单的示例,看看如何创建和保存会话。我们之前构建了一个简单的登录系统(请参阅 Django 表单处理章节和 Django Cookie 处理章节)。让我们将用户名保存在一个 cookie 中,因此如果不是注销,在访问登录页面时,你将看不到登录表单。基本上,让我们通过在服务器端保存 cookie 来使我们在 Django 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)。

Some More Possible Actions Using Sessions

我们已经了解了如何存储和访问会话,但了解请求的会话属性还有一些其他有用的操作,如下所示:

  1. set_expiry (value) - 设置会话的过期时间。

  2. get_expiry_age() - 返回此会话过期前剩余的秒数。

  3. get_expiry_date() - 返回此会话的过期日期。

  4. clear_expired() - 从会话存储中删除过期的会话。

  5. get_expire_at_browser_close() - 根据用户关闭其 Web 浏览器时其会话 cookie 是否过期,返回 True 或 False。

Django - Caching

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

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 缓存框架的一个优点是可以缓存 −

  1. 特定视图的输出。

  2. 模板的一部分。

  3. Your entire site.

要在 Django 中使用缓存,首先需要设置缓存的存放位置。缓存框架提供了多种可能选项 - 可以将缓存保存到数据库、文件系统或直接保存在内存中。设置在项目的 settings.py 文件中完成。

Setting Up Cache in Database

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

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

要使此设置起作用并完成设置,我们需要创建名为`my_table_name`的缓存表。为此,你需要执行以下操作 −

python manage.py createcachetable

Setting Up Cache in File System

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

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

Setting Up Cache in Memory

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

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

Or

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

Caching the Entire Site

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

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

请注意,这里的顺序很重要,更新应在获取中间件之前。

然后在同一文件中,你需要设置 −

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

Caching a View

如果你不想缓存整个站点,可以缓存一个特定视图。这可以通过使用 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 分钟。

Note − 如上所述,以上视图映射到 −

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 中不再需要它了。

Caching a Template Fragment

你也可以使用 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 - Comments

在开始之前,请注意 Django Comments 框架在 1.5 版本后已弃用。现在,你可以使用外部功能执行此操作,但如果你仍然想使用它,它仍包含在 1.6 和 1.7 版本中。从 1.8 版本开始,它已不存在,但你仍然可以在其他 GitHub 帐户上获取代码。

注释框架能让你很轻松地为应用程序中的任何模型添加注释。

若要开始使用 Django 注释框架 −

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

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'

同步 db,以创建所有注释表或集合 −

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 Model

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 view

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 template

{% 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 %}

最后,将 URL 映射到我们的 hello 视图 −

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

现在,

  1. 在我们的模板 (hello.html) 中,使用 − 载入注释框架 {% load comments %}

  2. 我们从该视图传递的 Dreamreal 对象获取评论数量 − {% get_comment_count for dreamreal as comment_count %}

  3. 我们为这些对象获取评论列表 − {% render_comment_list for dreamreal %}

  4. 我们显示默认的评论表单 − {% 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 class 进行子类化来创建 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})
  1. 在我们的提要类中, titlelinkdescription 属性对应于标准 RSS &lt;title&gt;&lt;link&gt;&lt;description&gt; 元素。

  2. items 方法返回应作为项元素添加到提要中的元素。在我们的示例中,返回的是最近五条评论。

  3. item_title 方法将获取作为我们提要项标题的内容。在我们的示例中,标题是用户名。

  4. item_description 方法将获取作为我们提要项描述的内容。在我们的示例中,是评论本身。

  5. 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。

Using Django-dajax

首先要做的是安装 django-dajax。可以使用 easy_install 或 pip 完成此操作 −

$ pip install django_dajax
$ easy_install django_dajax

这将自动安装 django-dajaxice,这是 django-dajax 所需的。然后我们需要配置 dajax 和 dajaxice。

在 INSTALLED_APPS 选项中,在项目的 settings.py 中添加 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 静态 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

Note − 有时 jquery.dajax.core.js 可能丢失了,如果遇到这种情况,只需下载源代码,并将该文件放入静态文件夹中即可。

访问 /myapp/dreamreal/ 后,您将看到以下屏幕 −

using django dajax

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

using django dajax response