Django 项目是一个定制框架,它源自一个在线新闻 Web 站点,于 2005 年以开源的形式被释放出来。Django 框架的核心组件有:
-
用于创建模型的对象关系映射
-
为最终用户设计的完美管理界面
-
一流的 URL 设计
-
设计者友好的模板语言
-
缓存系统
设计你的模型(model)
尽管你在 Django 中可以不使用数据库,但是它提供了一个完善的可以用 Python 代码描述你的数据库结构的对象关联映射(ORM)。数据模型语法 提供了许多丰富的方法来展现你的模型 – 到目前为止,它已经解决了两个多年积累下来数据库架构问题。下面是个简单的例子,可能被保存为 mysite/news/models.py:
-
class Reporter(models.Model):
-
full_name = models.CharField(max_length=70)
-
-
def __unicode__(self):
-
return self.full_name
-
-
class Article(models.Model):
-
pub_date = models.DateField()
-
headline = models.CharField(max_length=200)
-
content = models.TextField()
-
reporter = models.ForeignKey(Reporter)
-
-
def __unicode__(self):
-
return self.headline
下一步,运行 Django 命令行工具来自动创建数据库表:
manage.py syncdb
syncdb 命令会查找你所有可用的模型(models)然后在你的数据库中创建还不存在的数据库表。
设计你的 URLs
一个干净的,优雅的 URL 方案是一个高质量 Web 应用程序的重要细节。 Django 鼓励使用漂亮的 URL 设计,并且不鼓励把没必要的东西放到 URLs 里面,像 .php 或 .asp.为了给一个 app 设计 URLs,你需要创建一个 Python 模块叫做 :doc:`URLconf `。这是一个你的 app 内容目录, 它包含一个简单的 URL 匹配模式与 Python 回调函数间的映射关系。这有助于解耦 Python 代码和 URLs 。
这是针对上面 Reporter/Article 例子所配置的 URLconf 大概样子:
-
from django.conf.urls import patterns
-
-
urlpatterns = patterns('',
-
(r'^articles/(\d{4})/$', 'news.views.year_archive'),
-
(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
-
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
-
)
上面的代码映射了 URLs ,从一个简单的正则表达式,到 Python 回调函数(“views”)所在的位置。 正则表达式通过圆括号来“捕获” URLs 中的值。当一个用户请求一个页面时, Django 将按照顺序去匹配每一个模式,并停在第一个匹配请求的 URL 上。(如果没有匹配到, Django 将会展示一个404的错误页面。) 整个过程是极快的,因为在加载时正则表达式就进行了编译。一旦有一个正则表达式匹配上了,Django 将导入和调用对应的视图,它其实就是一个简单的 Python 函数。每个视图将得到一个 request 对象 – 它包含了 request 的 meta 信息 – 和正则表达式所捕获到的值。
例如:如果一个用户请求了个 URL “/articles/2005/05/39323/”, Django 将会这样调用函数 news.views.article_detail(request, '2005', '05', '39323').
编写你的视图(views)
每个视图只负责两件事中的一件:返回一个包含请求页面内容的 HttpResponse 对象; 或抛出一个异常如 Http404 。至于其他就靠你了。通常,一个视图会根据参数来检索数据,加载一个模板并且根据该模板来呈现检索出来的数据。 下面是个接上例的 year_archive 例子
-
def year_archive(request, year):
-
a_list = Article.objects.filter(pub_date__year=year)
-
return render_to_response('news/year_archive.html', {'year': year, 'article_list': a_list})
这个例子使用了 Django 的 :doc:`模板系统 `,该模板系统功能强大且简单易用,甚至非编程人员也会使用。
下面介绍一个简单的小例子
创建一个项目
如果这是你第一次使用 Django ,那么你必须进行一些初始设置。也就是通过自动生成代码来建立一个 Django 项目 project – 一个 Django 项目的设置集,包含了数据库配置、 Django 详细选项设置和应用特性配置。
在命令行中,使用 cd 命令进入你想存储代码所在的目录,然后运行以下命令:
django-admin.py startproject mysite
在版本1.6中,如下目录结构会被创建出来:
-
mysite/
-
manage.py
-
mysite/
-
__init__.py
-
settings.py
-
urls.py
-
wsgi.py
启动开发服务器
执行“python manage.py runserver”命令,就启动了一个纯粹的由 Python 编写的轻量级 Web 服务器。**不要** 在任何类似生产环境中使用此服务器。它仅适用于开发环境。生产环境可以用apache + wsgi;也可以用Tornado做服务,再用nginx做反向代理,因为Tornado需要用nginx来多开进程,提高并发量。
如果你想改变服务器 IP ,把它和端口号一起传递即可。因此,要监听所有公共 IP 地址,使用:
python manage.py runserver 0.0.0.0:8000
数据库设置
现在,编辑 mysite/settings.py 。 这是一个普通的 Python 模块,包含了代表 Django 设置的模块级变量。 更改 DATABASES 中 'default' 下的以下键的值,以匹配您的数据库连接设置。如果你是新建数据库,我们建议只使用 SQLite ,将 ENGINE 改为 'django.db.backends.sqlite3' 并且将 NAME 设置为你想存放数据库的地方。 SQLite 是内置在 Python 中的,因此你不需要安装任何东西来支持你的数据库。
同时,注意文件底部的 INSTALLED_APPS 设置。它保存了当前 Django 实例已激活的所有 Django 应用。每个应用可以被多个项目使用,而且你可以打包和分发给其他人在他们的项目中使用。默认情况下,:setting:INSTALLED_APPS 包含以下应用,这些都是由 Django 提供的:
-
django.contrib.auth – 身份验证系统。
-
django.contrib.contenttypes – 内容类型框架。
-
django.contrib.sessions – session 框架。
-
django.contrib.sites – 网站管理框架。
-
django.contrib.messages – 消息框架。
-
django.contrib.staticfiles – 静态文件管理框架。
所有这些应用中每个应用至少使用一个数据库表,
所以在使用它们之前我们需要创建数据库中的表。要做到这一点,请运行以下命令:
python manage.py syncdb
如果你感兴趣,可以在你的数据库命令行下输入:``dt`` (PostgreSQL), SHOW TABLES; (MySQL), 或 .schema (SQLite) 来列出 Django 所创建的表。
创建应用
要创建你的应用,请确认与 manage.py 文件在同一的目录下并输入以下命令:
python manage.py startapp polls
这将创建一个 polls 目录,其展开的样子如下所示::
polls/
__init__.py
models.py
tests.py
views.py
项目 ( Projects ) vs. 应用 ( apps )之间有什么不同之处?应用是一个提供功能的 Web 应用 – 例如:一个博客系统、一个公共记录的数据库或者一个简单的投票系统。 项目是针对一个特定的 Web 网站相关的配置和其应用的组合。一个项目可以包含多个应用。一个应用可以在多个项目中使用。
你的应用可以存放在 Python path 中的任何位置。在本教材中,我们将通过你的 manage.py 文件创建我们的投票应用,以便它可以作为顶层模块导入,而不是作为 mysite 的子模块。
创建模型
在 Django 中编写一个有数据库支持的 Web 应用的第一步就是定义你的模型 – 从本质上讲就是数据库设计及其附加的元数据。模型是有关你数据的唯一且明确的数据源。它包含了你所要存储的数据的基本字段和行为。 Django 遵循 DRY 原则 。目标是为了只在一个地方定义你的数据模型就可从中自动获取数据。在这简单的投票应用中,我们将创建两个模型: Poll 和 Choice``。``Poll 有问题和发布日期两个字段。``Choice`` 有两个字段: 选项 ( choice ) 的文本内容和投票数。每一个 Choice 都与一个 Poll 关联。
这些概念都由简单的 Python 类来表现。编辑 polls/models.py 文件后如下所示:
-
from django.db import models
-
-
class Poll(models.Model):
-
question = models.CharField(max_length=200)
-
pub_date = models.DateTimeField('date published')
-
-
class Choice(models.Model):
-
poll = models.ForeignKey(Poll)
-
choice_text = models.CharField(max_length=200)
-
votes = models.IntegerField(default=0)
代码很简单。每个模型都由继承自 django.db.models.Model 子类的类来描述。 每个模型都有一些类变量,每一个类变量都代表了一个数据库字段。每个字段由一个 Field 的实例来表现 – 比如 CharField 表示字符类型的字段和 DateTimeField 表示日期时间型的字段。这会告诉 Django 每个字段都保存了什么类型的数据。每一个 Field 实例的名字就是字段的名字(如: question 或者 pub_date ),其格式属于亲和机器式的。在你的 Python 的代码中会使用这个值,而你的数据库会将这个值作为表的列名。
你可以在初始化 Field 实例时使用第一个位置的可选参数来指定人类可读的名字。这在Django的内省部分中被使用到了,而且兼作文档的一部分来增强代码的可读性。若字段未提供该参数,Django 将使用符合机器习惯的名字。在本例中,我们仅定义了一个符合人类习惯的字段名 Poll.pub_date 。对于模型中的其他字段,机器名称就已经足够替代人类名称了。
一些 Field 实例是需要参数的。 例如 CharField 需要你指定 :attr:`~django.db.models.CharField.max_length`。这不仅适用于数据库结构,以后我们还会看到也用于数据验证中。
一个 Field 实例可以有不同的可选参数; 在本例中,我们将 votes 的 default 的值设为 0 。
最后,注意我们使用了 ForeignKey 定义了一个关联。它告诉 Django 每一个``Choice`` 关联一个 Poll 。 Django 支持常见数据库的所有关联:多对一( many-to-ones ),多对多( many-to-manys ) 和 一对一 ( one-to-ones )。
激活模型
刚才那点模型代码提供给 Django 大量信息。有了这些 Django 就可以做:
-
为该应用创建对应的数据库架构 (CREATE TABLE statements) 。
-
为 Poll 和 Choice 对象创建 Python 访问数据库的 API 。
但首先,我们需要告诉我们的项目已经安装了 polls 应用。再次编辑 settings.py 文件,在 INSTALLED_APPS 设置中加入 'polls' 字符。因此结果如下所示:
-
INSTALLED_APPS = (
-
'django.contrib.auth',
-
'django.contrib.contenttypes',
-
'django.contrib.sessions',
-
'django.contrib.sites',
-
'django.contrib.messages',
-
'django.contrib.staticfiles',
-
# Uncomment the next line to enable the admin:
-
# 'django.contrib.admin',
-
# Uncomment the next line to enable admin documentation:
-
# 'django.contrib.admindocs',
-
'polls',
-
)
现在 Django 已经知道包含了 polls 应用。让我们运行如下命令:
python manage.py sql polls
你将看到类似如下所示内容 ( 有关投票应用的 CREATE TABLE SQL 语句 ):
-
BEGIN;
-
CREATE TABLE "polls_poll" (
-
"id" serial NOT NULL PRIMARY KEY,
-
"question" varchar(200) NOT NULL,
-
"pub_date" timestamp with time zone NOT NULL
-
);
-
CREATE TABLE "polls_choice" (
-
"id" serial NOT NULL PRIMARY KEY,
-
"poll_id" integer NOT NULL REFERENCES "polls_poll" ("id") DEFERRABLE INITIALLY DEFERRED,
-
"choice_text" varchar(200) NOT NULL,
-
"votes" integer NOT NULL
-
);
-
COMMIT
现在,再次运行 syncdb 命令在你的数据库中创建这些模型对应的表:
python manage.py syncdb
syncdb 命令会给在 INSTALLED_APPS 中有但数据库中没有对应表的应用执行 sqlall 操作。 该操作会为你上一次执行 syncdb 命令以来在项目中添加的任何应用创建对应的表、初始化数据和创建索引。 syncdb 命令只要你喜欢就可以任意调用,并且它仅会创建不存在的表。
玩弄 API
现在,我们进入 Python 的交互式 shell 中玩弄 Django 提供给你的 API 。要调用 Python sell ,使用如下命令:
python manage.py shell
我们当前使用的环境不同于简单的输入 “python” 进入的 shell 环境,因为 manage.py 设置了 DJANGO_SETTINGS_MODULE 环境变量,该变量给定了 Django 需要导入的 settings.py 文件所在路径。若你不想使用 manage.py ,也是没有问题的。 仅需要将 DJANGO_SETTINGS_MODULE 环境变量值设为 mysite.settings 并在与 manage.py 文件所在同一目录下运行 python ( 或确保目录在 Python path 下,那 import mysite 就可以了 )。
一旦你进入了 shell,就可通过 database API 来浏览数据:
-
>>> from polls.models import Poll, Choice # Import the model classes we just wrote.
-
-
# 系统中还没有 polls 。
-
>>> Poll.objects.all()
-
[]
-
-
# 创建一个新 Poll 。
-
# 在默认配置文件中时区支持配置是启用的,
-
# 因此 Django 希望为 pub_date 字段获取一个 datetime with tzinfo 。使用了 timezone.now()
-
# 而不是 datetime.datetime.now() 以便获取正确的值。
-
>>> from django.utils import timezone
-
>>> p = Poll(question="What's new?", pub_date=timezone.now())
-
-
# 保存对象到数据库中。你必须显示调用 save() 方法。
-
>>> p.save()
-
-
# 现在对象拥有了一个ID 。请注意这可能会显示 "1L" 而不是 "1",取决于
-
# 你正在使用的数据库。 这没什么大不了的,它只是意味着你的数据库后端
-
# 喜欢返回的整型数作为 Python 的长整型对象而已。
-
>>> p.id
-
1
-
-
# 通过 Python 属性访问数据库中的列。
-
>>> p.question
-
"What's new?"
-
>>> p.pub_date
-
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)
-
-
# 通过改为属性值来改变值,然后调用 save() 方法。
-
>>> p.question = "What's up?"
-
>>> p.save()
-
-
# objects.all() 用以显示数据库中所有的 polls 。
-
>>> Poll.objects.all()
-
[<Poll: Poll object>]
请稍等。``
`` 这样显示对象绝对是无意义的。 让我们编辑 polls 模型( 在 polls/models.py 文件中 ) 并且给 Poll 和 Choice 都添加一个 __unicode__() 方法来修正此错误,给你的模型添加 __unicode__() 方法是很重要的, 不仅是让你在命令行下有明确提示,而且在 Django 自动生成的管理界面中也会使用到对象的呈现。
-
class Poll(models.Model):
-
# ...
-
def __unicode__(self):
-
return self.question
-
-
class Choice(models.Model):
-
# ...
-
def __unicode__(self):
-
return self.choice_text
保存这些更改并且再次运行 python manage.py shell 以开启一个新的 Python shell:
-
>>> from polls.models import Poll, Choice
-
-
# 确认我们附加的 __unicode__() 正常运行。
-
>>> Poll.objects.all()
-
[<Poll: What's up?>]
-
-
# Django 提供了一个丰富的数据库查询 API ,
-
# 完全由关键字参数来驱动。
-
>>> Poll.objects.filter(id=1)
-
[>]
-
>>> Poll.objects.filter(question__startswith='What')
-
[<Poll: What's up?>]
-
-
# 获取今年发起的投票。
-
>>> from django.utils import timezone
-
>>> current_year = timezone.now().year
-
>>> Poll.objects.get(pub_date__year=current_year)
-
>
-
-
# 请求一个不存在的 ID ,这将引发一个异常。
-
>>> Poll.objects.get(id=2)
-
Traceback (most recent call last):
-
...
-
DoesNotExist: Poll matching query does not exist. Lookup parameters were {'id': 2}
-
-
# 根据主键查询是常见的情况,因此 Django 提供了一个
-
# 主键精确查找的快捷方式。
-
# 以下代码等同于 Poll.objects.get(id=1).
-
>>> Poll.objects.get(pk=1)
-
<Poll: What's up?>
-
-
# 确认我们自定义方法正常运行。
-
>>> p = Poll.objects.get(pk=1)
-
>>> p.was_published_recently()
-
True
-
-
# 给 Poll 设置一些 Choices 。通过 create 方法调用构造方法去创建一个新
-
# Choice 对象实例,执行 INSERT 语句后添加该 choice 到
-
# 可用的 choices 集中并返回这个新建的 Choice 对象实例。 Django 创建了
-
# 一个保存外键关联关系的集合 ( 例如 poll 的 choices) 以便可以通过 API
-
# 去访问。
-
>>> p = Poll.objects.get(pk=1)
-
-
# 从关联对象集中显示所有 choices -- 到目前为止还没有。
-
>>> p.choice_set.all()
-
[]
-
-
# 创建三个 choices 。
-
>>> p.choice_set.create(choice_text='Not much', votes=0)
-
-
>>> p.choice_set.create(choice_text='The sky', votes=0)
-
-
>>> c = p.choice_set.create(choice_text='Just hacking again', votes=0)
-
-
# Choice 对象拥有访问它们关联的 Poll 对象的 API 。
-
>>> c.poll
-
>
-
-
# 反之亦然: Poll 对象也可访问 Choice 对象。
-
>>> p.choice_set.all()
-
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
-
>>> p.choice_set.count()
-
3
-
-
# 只要你需要 API 会自动连续关联。
-
# 使用双下划线来隔离关联。
-
# 只要你想要几层关联就可以有几层关联,没有限制。
-
# 寻找和今年发起的任何 poll 有关的所有 Choices
-
# ( 重用我们在上面建立的 'current_year' 变量 )。
-
>>> Choice.objects.filter(poll__pub_date__year=current_year)
-
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
-
-
# 让我们使用 delete() 删除 choices 中的一个。
-
>>> c = p.choice_set.filter(choice_text__startswith='Just hacking')
-
>>> c.delete()
django命令解释
-
django-admin.py startproject mysite
-
该命令在当前目录创建一个 mysite 目录。
-
-
python manage.py runserver 8080
-
更改服务器端口号
-
-
python manage.py shell
-
启动交互界面
-
-
python manage.py startapp books
-
创建一个app,名为books
-
-
python manage.py validate
-
验证Django数据模型代码是否有错误
-
-
python manage.py sqlall books
-
为模型产生sql代码
-
-
python manage.py syncdb
-
运行sql语句,创建模型相应的Table
-
-
python manage.py dbshell
-
启动数据库的命令行工具
-
-
manage.py sqlall books
-
查看books这个app下所有的表
-
-
python manage.py syncdb
-
同步数据库,生成管理界面使用的额外的数据库表
详细的帮助和指导,参考