在Django框架中运行Python应用全攻略
admin
2023-07-31 02:25:43
0

我们来假定下面的这些概念、字段和关系:

  •     一个作者有姓,有名及email地址。
  •     出版商有名称,地址,所在城市、省,国家,网站。
  •     书籍有书名和出版日期。 它有一个或多个作者(和作者是多对多的关联关系[many-to-many]), 只有一个出版商(和出版商是一对多的关联关系[one-to-many],也被称作外键[foreign key])

第一步是用Python代码来描述它们。 打开由“ startapp“ 命令创建的models.py 并输入下面的内容:

from django.db import models

class Publisher(models.Model):
 name = models.CharField(max_length=30)
 address = models.CharField(max_length=50)
 city = models.CharField(max_length=60)
 state_province = models.CharField(max_length=30)
 country = models.CharField(max_length=50)
 website = models.URLField()

class Author(models.Model):
 first_name = models.CharField(max_length=30)
 last_name = models.CharField(max_length=40)
 email = models.EmailField()

class Book(models.Model):
 title = models.CharField(max_length=100)
 authors = models.ManyToManyField(Author)
 publisher = models.ForeignKey(Publisher)
 publication_date = models.DateField()

让我们来快速讲解一下这些代码的含义。 首先要注意的事是每个数据模型都是 django.db.models.Model 的子类。它的父类 Model 包含了所有必要的和数据库交互的方法,并提供了一个简洁漂亮的定义数据库字段的语法。 信不信由你,这些就是我们需要编写的通过Django存取基本数据的所有代码。

每个模型相当于单个数据库表,每个属性也是这个表中的一个字段。 属性名就是字段名,它的类型(例如 CharField )相当于数据库的字段类型 (例如 varchar )。例如, Publisher 模块等同于下面这张表(用PostgreSQL的 CREATE TABLE 语法描述):

CREATE TABLE \"books_publisher\" (
 \"id\" serial NOT NULL PRIMARY KEY,
 \"name\" varchar(30) NOT NULL,
 \"address\" varchar(50) NOT NULL,
 \"city\" varchar(60) NOT NULL,
 \"state_province\" varchar(30) NOT NULL,
 \"country\" varchar(50) NOT NULL,
 \"website\" varchar(200) NOT NULL
);

事实上,正如过一会儿我们所要展示的,Django 可以自动生成这些 CREATE TABLE 语句。

“每个数据库表对应一个类”这条规则的例外情况是多对多关系。 在我们的范例模型中, Book 有一个 多对多字段 叫做 authors 。 该字段表明一本书籍有一个或多个作者,但 Book 数据库表却并没有 authors 字段。 相反,Django创建了一个额外的表(多对多连接表)来处理书籍和作者之间的映射关系。

请查看附录 B 了解所有的字段类型和模型语法选项。

最后需要注意的是,我们并没有显式地为这些模型定义任何主键。 除非你单独指明,否则Django会自动为每个模型生成一个自增长的整数主键字段每个Django模型都要求有单独的主键。
模型安装

完成这些代码之后,现在让我们来在数据库中创建这些表。 要完成该项工作,第一步是在 Django 项目中 激活 这些模型。 将 books app 添加到配置文件的已安装应用列表中即可完成此步骤。

再次编辑 settings.py 文件, 找到 INSTALLED_APPS 设置。 INSTALLED_APPS 告诉 Django 项目哪些 app 处于激活状态。 缺省情况下如下所示:

INSTALLED_APPS = (
 \'django.contrib.auth\',
 \'django.contrib.contenttypes\',
 \'django.contrib.sessions\',
 \'django.contrib.sites\',
)

把这四个设置前面加#临时注释起来。 (这四个app是经常使用到的,我们将在后续章节里讨论如何使用它们)。同时,注释掉MIDDLEWARE_CLASSES的默认设置条目,因为这些条目是依赖于刚才我们刚在INSTALLED_APPS注释掉的apps。 然后,添加“ ‘mysite.books\’“ 到“ INSTALLED_APPS“ 的末尾,此时设置的内容看起来应该是这样的:

MIDDLEWARE_CLASSES = (
 # \'django.middleware.common.CommonMiddleware\',
 # \'django.contrib.sessions.middleware.SessionMiddleware\',
 # \'django.contrib.auth.middleware.AuthenticationMiddleware\',
)

INSTALLED_APPS = (
 # \'django.contrib.auth\',
 # \'django.contrib.contenttypes\',
 # \'django.contrib.sessions\',
 # \'django.contrib.sites\',
 \'mysite.books\',
)

(就像我们在上一章设置TEMPLATE_DIRS所提到的逗号,同样在INSTALLED_APPS的末尾也需添加一个逗号,因为这是个单元素的元组。 另外,本书的作者喜欢在 每一个 tuple元素后面加一个逗号,不管它是不是 只有一个元素。 这是为了避免忘了加逗号,而且也没什么坏处。)

\’mysite.books\’指示我们正在编写的books app。 INSTALLED_APPS 中的每个app都使用 Python的路径描述,包的路径,用小数点“.”间隔。

现在我们可以创建数据库表了。 首先,用下面的命令验证模型的有效性:

python manage.py validate

validate 命令检查你的模型的语法和逻辑是否正确。 如果一切正常,你会看到 0 errors found 消息。如果出错,请检查你输入的模型代码。 错误输出会给出非常有用的错误信息来帮助你修正你的模型。

一旦你觉得你的模型可能有问题,运行 python manage.py validate 。 它可以帮助你捕获一些常见的模型定义错误。

模型确认没问题了,运行下面的命令来生成 CREATE TABLE 语句(如果你使用的是Unix,那么可以启用语法高亮):

python manage.py sqlall books

在这个命令行中, books 是app的名称。 和你运行 manage.py startapp 中的一样。执行之后,输出如下:

BEGIN;
CREATE TABLE \"books_publisher\" (
 \"id\" serial NOT NULL PRIMARY KEY,
 \"name\" varchar(30) NOT NULL,
 \"address\" varchar(50) NOT NULL,
 \"city\" varchar(60) NOT NULL,
 \"state_province\" varchar(30) NOT NULL,
 \"country\" varchar(50) NOT NULL,
 \"website\" varchar(200) NOT NULL
)
;
CREATE TABLE \"books_author\" (
 \"id\" serial NOT NULL PRIMARY KEY,
 \"first_name\" varchar(30) NOT NULL,
 \"last_name\" varchar(40) NOT NULL,
 \"email\" varchar(75) NOT NULL
)
;
CREATE TABLE \"books_book\" (
 \"id\" serial NOT NULL PRIMARY KEY,
 \"title\" varchar(100) NOT NULL,
 \"publisher_id\" integer NOT NULL REFERENCES \"books_publisher\" (\"id\") DEFERRABLE INITIALLY DEFERRED,
 \"publication_date\" date NOT NULL
)
;
CREATE TABLE \"books_book_authors\" (
 \"id\" serial NOT NULL PRIMARY KEY,
 \"book_id\" integer NOT NULL REFERENCES \"books_book\" (\"id\") DEFERRABLE INITIALLY DEFERRED,
 \"author_id\" integer NOT NULL REFERENCES \"books_author\" (\"id\") DEFERRABLE INITIALLY DEFERRED,
 UNIQUE (\"book_id\", \"author_id\")
)
;
CREATE INDEX \"books_book_publisher_id\" ON \"books_book\" (\"publisher_id\");
COMMIT;

注意:

  •     自动生成的表名是app名称( books )和模型的小写名称 ( publisher , book , author )的组合。你可以参考附录B重写这个规则。
  •     我们前面已经提到,Django为每个表格自动添加加了一个 id 主键, 你可以重新设置它。
  •     按约定,Django添加 \”_id\” 后缀到外键字段名。 你猜对了,这个同样是可以自定义的。
  •     外键是用 REFERENCES 语句明确定义的。
  •     这些 CREATE TABLE 语句会根据你的数据库而作调整,这样象数据库特定的一些字段例如:(MySQL),auto_increment(PostgreSQL),serial(SQLite),都会自动生成。integer primary key 同样的,字段名称也是自动处理(例如单引号还好是双引号)。 例子中的输出是基于PostgreSQL语法的。

sqlall 命令并没有在数据库中真正创建数据表,只是把SQL语句段打印出来,这样你可以看到Django究竟会做些什么。 如果你想这么做的话,你可以把那些SQL语句复制到你的数据库客户端执行,或者通过Unix管道直接进行操作(例如,“ python manager.py sqlall books | psql mydb“ )。不过,Django提供了一种更为简易的提交SQL语句至数据库的方法: “ syncdb“ 命令

python manage.py syncdb

执行这个命令后,将看到类似以下的内容:

Creating table books_publisher
Creating table books_author
Creating table books_book
Installing index for books.Book model

syncdb 命令是同步你的模型到数据库的一个简单方法。 它会根据 INSTALLED_APPS 里设置的app来检查数据库, 如果表不存在,它就会创建它。 需要注意的是, syncdb 并 不能将模型的修改或删除同步到数据库;如果你修改或删除了一个模型,并想把它提交到数据库,syncdb并不会做出任何处理。 (更多内容请查看本章最后的“修改数据库的架构”一段。)

如果你再次运行 python manage.py syncdb ,什么也没发生,因为你没有添加新的模型或者 添加新的app。因此,运行python manage.py syncdb总是安全的,因为它不会重复执行SQL语句。

如果你有兴趣,花点时间用你的SQL客户端登录进数据库服务器看看刚才Django创建的数据表。 你可以手动启动命令行客户端(例如,执行PostgreSQL的“ psql“ 命令),也可以执行 “ python manage.py dbshell“ ,这个命令将依据“ DATABASE_SERVER“ 的里设置自动检测使用哪种命令行客户端。 常言说,后来者居上。
基本数据访问

一旦你创建了模型,Django自动为这些模型提供了高级的Python API。 运行 python manage.py shell 并输入下面的内容试试看:

>>> from books.models import Publisher
>>> p1 = Publisher(name=\'Apress\', address=\'2855 Telegraph Avenue\',
...  city=\'Berkeley\', state_province=\'CA\', country=\'U.S.A.\',
...  website=\'http://www.apress.com/\')
>>> p1.save()
>>> p2 = Publisher(name=\"O\'Reilly\", address=\'10 Fawcett St.\',
...  city=\'Cambridge\', state_province=\'MA\', country=\'U.S.A.\',
...  website=\'http://www.oreilly.com/\')
>>> p2.save()
>>> publisher_list = Publisher.objects.all()
>>> publisher_list
[, ]

这短短几行代码干了不少的事。 这里简单的说一下:

  •     首先,导入Publisher模型类, 通过这个类我们可以与包含 出版社 的数据表进行交互。
  •     接着,创建一个“ Publisher“ 类的实例并设置了字段“ name, address“ 等的值。
  •     调用该对象的 save() 方法,将对象保存到数据库中。 Django 会在后台执行一条 INSERT 语句。
  •     最后,使用“ Publisher.objects“ 属性从数据库取出出版商的信息,这个属性可以认为是包含出版商的记录集。 这个属性有许多方法, 这里先介绍调用“ Publisher.objects.all()“ 方法获取数据库中“ Publisher“ 类的所有对象。这个操作的幕后,Django执行了一条SQL “ SELECT“ 语句。

这里有一个值得注意的地方,在这个例子可能并未清晰地展示。 当你使用Django modle API创建对象时Django并未将对象保存至数据库内,除非你调用“ save()“ 方法:

p1 = Publisher(...)
# At this point, p1 is not saved to the database yet!
p1.save()
# Now it is.

如果需要一步完成对象的创建与存储至数据库,就使用“ objects.create()“ 方法。 下面的例子与之前的例子等价:

>>> p1 = Publisher.objects.create(name=\'Apress\',
...  address=\'2855 Telegraph Avenue\',
...  city=\'Berkeley\', state_province=\'CA\', country=\'U.S.A.\',
...  website=\'http://www.apress.com/\')
>>> p2 = Publisher.objects.create(name=\"O\'Reilly\",
...  address=\'10 Fawcett St.\', city=\'Cambridge\',
...  state_province=\'MA\', country=\'U.S.A.\',
...  website=\'http://www.oreilly.com/\')
>>> publisher_list = Publisher.objects.all()
>>> publisher_list

当然,你肯定想执行更多的Django数据库API试试看,不过,还是让我们先解决一点烦人的小问题。

添加模块的字符串表现

当我们打印整个publisher列表时,我们没有得到想要的有用信息,无法把““对象区分开来:

System Message: WARNING/2 (, line 872); backlink

Inline literal start-string without end-string.

System Message: WARNING/2 (, line 872); backlink

Inline literal start-string without end-string.

[, ]

我们可以简单解决这个问题,只需要为Publisher 对象添加一个方法 __unicode__() 。 __unicode__() 方法告诉Python如何将对象以unicode的方式显示出来。 为以上三个模型添加__unicode__()方法后,就可以看到效果了:

from django.db import models

class Publisher(models.Model):
 name = models.CharField(max_length=30)
 address = models.CharField(max_length=50)
 city = models.CharField(max_length=60)
 state_province = models.CharField(max_length=30)
 country = models.CharField(max_length=50)
 website = models.URLField()

 **def __unicode__(self):**
  **return self.name**

class Author(models.Model):
 first_name = models.CharField(max_length=30)
 last_name = models.CharField(max_length=40)
 email = models.EmailField()

 **def __unicode__(self):**
  **return u\'%s %s\' % (self.first_name, self.last_name)**

class Book(models.Model):
 title = models.CharField(max_length=100)
 authors = models.ManyToManyField(Author)
 publisher = models.ForeignKey(Publisher)
 publication_date = models.DateField()

 **def __unicode__(self):**
  **return self.title**

就象你看到的一样, __unicode__() 方法可以进行任何处理来返回对一个对象的字符串表示。 Publisher和Book对象的__unicode__()方法简单地返回各自的名称和标题,Author对象的__unicode__()方法则稍微复杂一些,它将first_name和last_name字段值以空格连接后再返回。

对__unicode__()的唯一要求就是它要返回一个unicode对象 如果“ __unicode__()“ 方法未返回一个Unicode对象,而返回比如说一个整型数字,那么Python将抛出一个“ TypeError“ 错误,并提示:”coercing to Unicode: need string or buffer, int found” 。

相关内容

热门资讯

500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
python查找阿姆斯特朗数 题目解释 如果一个n位正整数等于其各位数字的n次方之和,则称该数为阿姆斯特朗数。 例如1^3 + 5...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...