Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2384977
  • 博文数量: 328
  • 博客积分: 4302
  • 博客等级: 上校
  • 技术积分: 5486
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-01 11:14
个人简介

悲剧,绝对的悲剧,悲剧中的悲剧。

文章分类

全部博文(328)

文章存档

2017年(6)

2016年(18)

2015年(28)

2014年(73)

2013年(62)

2012年(58)

2011年(55)

2010年(28)

分类: Python/Ruby

2014-06-30 16:09:38

Django 项目是一个定制框架,它源自一个在线新闻 Web 站点,于 2005 年以开源的形式被释放出来。Django 框架的核心组件有:
  • 用于创建模型的对象关系映射
  • 为最终用户设计的完美管理界面
  • 一流的 URL 设计
  • 设计者友好的模板语言
  • 缓存系统

设计你的模型(model)


尽管你在 Django 中可以不使用数据库,但是它提供了一个完善的可以用 Python 代码描述你的数据库结构的对象关联映射(ORM)。数据模型语法 提供了许多丰富的方法来展现你的模型 – 到目前为止,它已经解决了两个多年积累下来数据库架构问题。下面是个简单的例子,可能被保存为 mysite/news/models.py:
  1. class Reporter(models.Model):
  2.     full_name = models.CharField(max_length=70)

  3.     def __unicode__(self):
  4.         return self.full_name

  5. class Article(models.Model):
  6.     pub_date = models.DateField()
  7.     headline = models.CharField(max_length=200)
  8.     content = models.TextField()
  9.     reporter = models.ForeignKey(Reporter)

  10.     def __unicode__(self):
  11.         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 大概样子:
  1. from django.conf.urls import patterns

  2. urlpatterns = patterns('',
  3.     (r'^articles/(\d{4})/$', 'news.views.year_archive'),
  4.     (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
  5.     (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
  6. )

上面的代码映射了 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 例子
  1. def year_archive(request, year):
  2.     a_list = Article.objects.filter(pub_date__year=year)
  3.     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中,如下目录结构会被创建出来:
  1. mysite/
  2.     manage.py
  3.     mysite/
  4.         __init__.py
  5.         settings.py
  6.         urls.py
  7.         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 提供的:
  1. django.contrib.auth – 身份验证系统。
  2. django.contrib.contenttypes – 内容类型框架。
  3. django.contrib.sessions – session 框架。
  4. django.contrib.sites – 网站管理框架。
  5. django.contrib.messages – 消息框架。
  6. 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 文件后如下所示:
  1. from django.db import models

  2. class Poll(models.Model):
  3.     question = models.CharField(max_length=200)
  4.     pub_date = models.DateTimeField('date published')

  5. class Choice(models.Model):
  6.     poll = models.ForeignKey(Poll)
  7.     choice_text = models.CharField(max_length=200)
  8.     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' 字符。因此结果如下所示:
  1. INSTALLED_APPS = (
  2.     'django.contrib.auth',
  3.     'django.contrib.contenttypes',
  4.     'django.contrib.sessions',
  5.     'django.contrib.sites',
  6.     'django.contrib.messages',
  7.     'django.contrib.staticfiles',
  8.     # Uncomment the next line to enable the admin:
  9.     # 'django.contrib.admin',
  10.     # Uncomment the next line to enable admin documentation:
  11.     # 'django.contrib.admindocs',
  12.     'polls',
  13. )

现在 Django 已经知道包含了 polls 应用。让我们运行如下命令:
python manage.py sql polls
你将看到类似如下所示内容 ( 有关投票应用的 CREATE TABLE SQL 语句 ):
  1. BEGIN;
  2. CREATE TABLE "polls_poll" (
  3.     "id" serial NOT NULL PRIMARY KEY,
  4.     "question" varchar(200) NOT NULL,
  5.     "pub_date" timestamp with time zone NOT NULL
  6. );
  7. CREATE TABLE "polls_choice" (
  8.     "id" serial NOT NULL PRIMARY KEY,
  9.     "poll_id" integer NOT NULL REFERENCES "polls_poll" ("id") DEFERRABLE INITIALLY DEFERRED,
  10.     "choice_text" varchar(200) NOT NULL,
  11.     "votes" integer NOT NULL
  12. );
  13. 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 来浏览数据:
  1. >>> from polls.models import Poll, Choice # Import the model classes we just wrote.

  2. # 系统中还没有 polls 。
  3. >>> Poll.objects.all()
  4. []

  5. # 创建一个新 Poll 。
  6. # 在默认配置文件中时区支持配置是启用的,
  7. # 因此 Django 希望为 pub_date 字段获取一个 datetime with tzinfo 。使用了 timezone.now()
  8. # 而不是 datetime.datetime.now() 以便获取正确的值。
  9. >>> from django.utils import timezone
  10. >>> p = Poll(question="What's new?", pub_date=timezone.now())

  11. # 保存对象到数据库中。你必须显示调用 save() 方法。
  12. >>> p.save()

  13. # 现在对象拥有了一个ID 。请注意这可能会显示 "1L" 而不是 "1",取决于
  14. # 你正在使用的数据库。 这没什么大不了的,它只是意味着你的数据库后端
  15. # 喜欢返回的整型数作为 Python 的长整型对象而已。
  16. >>> p.id
  17. 1

  18. # 通过 Python 属性访问数据库中的列。
  19. >>> p.question
  20. "What's new?"
  21. >>> p.pub_date
  22. datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

  23. # 通过改为属性值来改变值,然后调用 save() 方法。
  24. >>> p.question = "What's up?"
  25. >>> p.save()

  26. # objects.all() 用以显示数据库中所有的 polls 。
  27. >>> Poll.objects.all()
  28. [<Poll: Poll object>]
请稍等。```` 这样显示对象绝对是无意义的。 让我们编辑 polls 模型( 在 polls/models.py 文件中 ) 并且给 Poll 和 Choice 都添加一个 __unicode__() 方法来修正此错误,给你的模型添加 __unicode__() 方法是很重要的, 不仅是让你在命令行下有明确提示,而且在 Django 自动生成的管理界面中也会使用到对象的呈现。
  1. class Poll(models.Model):
  2.     # ...
  3.     def __unicode__(self):
  4.         return self.question

  5. class Choice(models.Model):
  6.     # ...
  7.     def __unicode__(self):
  8.         return self.choice_text
保存这些更改并且再次运行 python manage.py shell 以开启一个新的 Python shell:
  1. >>> from polls.models import Poll, Choice

  2. # 确认我们附加的 __unicode__() 正常运行。
  3. >>> Poll.objects.all()
  4. [<Poll: What's up?>]

  5. # Django 提供了一个丰富的数据库查询 API ,
  6. # 完全由关键字参数来驱动。
  7. >>> Poll.objects.filter(id=1)
  8. [>]
  9. >>> Poll.objects.filter(question__startswith='What')
  10. [<Poll: What's up?>]

  11. # 获取今年发起的投票。
  12. >>> from django.utils import timezone
  13. >>> current_year = timezone.now().year
  14. >>> Poll.objects.get(pub_date__year=current_year)
  15. >

  16. # 请求一个不存在的 ID ,这将引发一个异常。
  17. >>> Poll.objects.get(id=2)
  18. Traceback (most recent call last):
  19.     ...
  20. DoesNotExist: Poll matching query does not exist. Lookup parameters were {'id': 2}

  21. # 根据主键查询是常见的情况,因此 Django 提供了一个
  22. # 主键精确查找的快捷方式。
  23. # 以下代码等同于 Poll.objects.get(id=1).
  24. >>> Poll.objects.get(pk=1)
  25. <Poll: What's up?>

  26. # 确认我们自定义方法正常运行。
  27. >>> p = Poll.objects.get(pk=1)
  28. >>> p.was_published_recently()
  29. True

  30. # 给 Poll 设置一些 Choices 。通过 create 方法调用构造方法去创建一个新
  31. # Choice 对象实例,执行 INSERT 语句后添加该 choice 到
  32. # 可用的 choices 集中并返回这个新建的 Choice 对象实例。 Django 创建了
  33. # 一个保存外键关联关系的集合 ( 例如 poll 的 choices) 以便可以通过 API
  34. # 去访问。
  35. >>> p = Poll.objects.get(pk=1)

  36. # 从关联对象集中显示所有 choices -- 到目前为止还没有。
  37. >>> p.choice_set.all()
  38. []

  39. # 创建三个 choices 。
  40. >>> p.choice_set.create(choice_text='Not much', votes=0)

  41. >>> p.choice_set.create(choice_text='The sky', votes=0)

  42. >>> c = p.choice_set.create(choice_text='Just hacking again', votes=0)

  43. # Choice 对象拥有访问它们关联的 Poll 对象的 API 。
  44. >>> c.poll
  45. >

  46. # 反之亦然: Poll 对象也可访问 Choice 对象。
  47. >>> p.choice_set.all()
  48. [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
  49. >>> p.choice_set.count()
  50. 3

  51. # 只要你需要 API 会自动连续关联。
  52. # 使用双下划线来隔离关联。
  53. # 只要你想要几层关联就可以有几层关联,没有限制。
  54. # 寻找和今年发起的任何 poll 有关的所有 Choices
  55. # ( 重用我们在上面建立的 'current_year' 变量 )
  56. >>> Choice.objects.filter(poll__pub_date__year=current_year)
  57. [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]

  58. # 让我们使用 delete() 删除 choices 中的一个。
  59. >>> c = p.choice_set.filter(choice_text__startswith='Just hacking')
  60. >>> c.delete()


django命令解释


  1. django-admin.py startproject mysite
  2. 该命令在当前目录创建一个 mysite 目录。

  3. python manage.py runserver 8080
  4. 更改服务器端口号

  5. python manage.py shell
  6. 启动交互界面

  7. python manage.py startapp books
  8. 创建一个app,名为books

  9. python manage.py validate
  10. 验证Django数据模型代码是否有错误

  11. python manage.py sqlall books
  12. 为模型产生sql代码

  13. python manage.py syncdb
  14. 运行sql语句,创建模型相应的Table

  15. python manage.py dbshell
  16. 启动数据库的命令行工具

  17. manage.py sqlall books
  18. 查看books这个app下所有的表

  19. python manage.py syncdb
  20. 同步数据库,生成管理界面使用的额外的数据库表

详细的帮助和指导,参考
阅读(5340) | 评论(1) | 转发(3) |
给主人留下些什么吧!~~

xinguimeng2014-07-10 02:32:09

http://pan.baidu.com/s/1mgv9mkS