《老鸟python 系列》视频上线了,全网稀缺资源,涵盖python人工智能教程,爬虫教程,web教程,数据分析教程以及界面库和服务器教程,以及各个方向的主流实用项目,手把手带你从零开始进阶高手之路!点击 链接 查看详情

使用模型

阅读:378166756    分享到

经过上一节的学习,我们学会了使用模型中类的定义来转化为 mysql 数据库表的操作以及各种命令的使用。从本节开始,我们正式开始使用模型来做基于数据库的 Django 项目。

基本数据访问

一旦你创建了模型,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 object>, <Publisher: Publisher object>]

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

  • 首先,导入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: Publisher object>, <Publisher: Publisher object>]

我们可以简单解决这个问题,只需要为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() 方法可以进行任何处理来返回对一个对象的字符串表示。PublisherBook 对象的 unicode() 方法简单地返回各自的名称和标题,Author 对象的 unicode() 方法则稍微复杂一些,它将 first_namelast_name 字段值以空格连接后再返回。

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

Unicode对象

什么是 Unicode 对象呢?

你可以认为 unicode 对象就是一个 Python 字符串,它可以处理上百万不同类别的字符——从古老版本的 Latin 字符到非 Latin 字符,再到曲折的引用和艰涩的符号。

普通的 python 字符串是经过编码的,意思就是它们使用了某种编码方式(如 ASCII,ISO-8859-1 或者 UTF-8)来编码。如果你把奇特的字符(其它任何超出标准 128 个如 0-9 和 A-Z 之类的 ASCII 字符)保存在一个普通的 Python 字符串里,你一定要跟踪你的字符串是用什么编码的,否则这些奇特的字符可能会在显示或者打印的时候出现乱码。 当你尝试要将用某种编码保存的数据结合到另外一种编码的数据中,或者你想要把它显示在已经假定了某种编码的程序中的时候,问题就会发生。我们都已经见到过网页和邮件被???弄得乱七八糟。?????? 或者其它出现在奇怪位置的字符:这一般来说就是存在编码问题了。

但是 Unicode 对象并没有编码。它们使用 Unicode,一个一致的,通用的字符编码集。当你在 Python 中处理 Unicode 对象的时候,你可以直接将它们混合使用和互相匹配而不必去考虑编码细节。

Django 在其内部的各个方面都使用到了 Unicode 对象。模型 对象中,检索匹配方面的操作使用的是 Unicode 对象,视图 函数之间的交互使用的是 Unicode 对象,模板的渲染也是用的 Unicode 对象。通常,我们不必担心编码是否正确,后台会处理的很好。

注意,我们这里只是对 Unicode 对象进行非常浅显的概述,若要深入了解你可能需要查阅相关的资料。这是一个很好的起点:http://www.joelonsoftware.com/articles/Unicode.html。

为了让我们的修改生效,先退出 Python Shell,然后再次运行 python manage.py shell 进入。(这是保证代码修改生效的最简单方法。)现在 Publisher 对象列表容易理解多了。

>>> from books.models import Publisher
>>> publisher_list = Publisher.objects.all()
>>> publisher_list
[<Publisher: Apress>, <Publisher: O'Reilly>]

请确保你的每一个模型里都包含 unicode() 方法,这不只是为了交互时方便,也是因为 Django 会在其他一些地方用 unicode() 来显示对象。

最后,unicode() 也是一个很好的例子来演示我们怎么添加 行为 到模型里。 Django 的模型不只是为对象定义了数据库表的结构,还定义了对象的行为。unicode() 就是一个例子来演示模型知道怎么显示它们自己。

插入和更新数据

你已经知道怎么做了:先使用一些关键参数创建对象实例,如下:

>>> p = Publisher(name='Apress',
...         address='2855 Telegraph Ave.',
...         city='Berkeley',
...         state_province='CA',
...         country='U.S.A.',
...         website='http://www.apress.com/')

这个对象实例并 没有 对数据库做修改。在调用 save() 方法之前,记录并没有保存至数据库,像这样:

>>> p.save()

在 SQL 里,这大致可以转换成这样:

INSERT INTO books_publisher
    (name, address, city, state_province, country, website)
VALUES
    ('Apress', '2855 Telegraph Ave.', 'Berkeley', 'CA',
    'U.S.A.', 'http://www.apress.com/');

因为 Publisher 模型有一个自动增加的主键 id ,所以第一次调用 save() 还多做了一件事:计算这个主键的值并把它赋值给这个对象实例:

>>> p.id
52    # this will differ based on your own data

接下来再调用 save() 将不会创建新的记录,而只是修改记录内容(也就是 执行 UPDATE SQL语句,而不是 INSERT 语句):

>>> p.name = 'Apress Publishing'
>>> p.save()

前面执行的 save() 相当于下面的 SQL 语句:

UPDATE books_publisher SET
    name = 'Apress Publishing',
    address = '2855 Telegraph Ave.',
    city = 'Berkeley',
    state_province = 'CA',
    country = 'U.S.A.',
    website = 'http://www.apress.com'
WHERE id = 52;

注意,并不是只更新修改过的那个字段,所有的字段都会被更新。这个操作有可能引起竞态条件,这取决于你的应用程序。请参阅后面的“更新多个对象”小节以了解如何实现这种轻量的修改(只修改对象的部分字段)。

UPDATE books_publisher SET
    name = 'Apress Publishing'
WHERE id=52;

如果以上内容对您有帮助,请老板用微信扫一下赞赏码,赞赏后加微信号 birdpython 领取免费视频。


登录后评论