目录
前言
对现代的 Web 应用程序而言,视图逻辑经常需要与数据库交互。在数据库驱动型网站中,网站连接数据库服务器,从中检索数据,然后在网页中把数据显示出来。此外,可能还会提供让访客自行填充数据库的方式。Django 非常适合构建数据库驱动型网站,它提供了简单而强大的工具,易于使用 Python 执行数据库查询。下面就说明这个功能,即 Django 的数据库层。
配置数据库
settings.py
# Database
# ...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
• ENGINE 告诉 Django 使用哪个数据库引擎。本书的示例使用 SQLite,因此不用改,继续使用默认的
django.db.backends.sqlite3 。
• NAME 告诉 Django 数据库的名称。例如: 'NAME': 'mydb', 。
使用 Python 定义模型的好处
• 内省(introspection)有开销,而且不完美。为了提供便利的数据访问 API,Django 需要以某种方式知晓数据库布局,而这一需求有两种实现方式。第一种是使用 Python 明确描述数据,第二种是在运行时内省数据库,推知数据模型。第二种方式在一个地方存储表的元数据,看似更简单,其实会导致几个问题。首先,运行时内省数据库肯定有消耗。如果每次执行请求,或者只是初始化 Web 服务器都要内省数据库,那带来的消耗是无法接受的。(有些人觉那点消耗不算事,然而 Django 的开发者可是在想方设法努力降低框架的消耗。)其次,有些数据库,尤其是旧版 MySQL,存储的元数据不足以完成内省。
• Python 编写起来让人心情舒畅,而且使用 Python 编写所有代码无需频繁让大脑切换情境。在一个编程环境(思维)中待久了,有助于提升效率。在 SQL 和 Python 之间换来换去容易打断状态。
• 把数据模型保存在代码中比保存在数据库中易于做版本控制,易于跟踪数据布局的变化。
• SQL 对数据布局的元数据只有部分支持。例如,多数数据库系统没有提供专门表示电子邮件地址或URL 的数据类型。而 Django 模型有。高层级的数据结构有助于提升效率,让代码更便于复用。
• 不同数据库平台使用的 SQL 不一致。分发 Web 应用程序时,更务实的做法是分发一个描述数据布局的 Python 模块,而不是分别针对MySQL、PostgreSQL 和 SQLite 的 CREATE TABLE 语句。
创建模型
在编译器命令行执行或定位到项目根目录
django-admin startapp books
models.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
# Create your models here.
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()
settings.py 添加books模型
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'books',
)
检查框架,如下即可
python manage.py check
确认模型有效之后,运行下述命令,告诉 Django 你对模型做了修改(这里是新建了模型):
python manage.py makemigrations books
Django 把对模型(也就是数据库模式)的改动存储在迁移中,迁移就是磁盘中的文件。运行上述命令后,books 应用的 migrations 文件夹里会出现一个名为 0001_initial.py 的文件。 migrate 命令会查看最新的迁移文件,自动更新数据库模式;不过,我们先来看看将运行的 SQL。 sqlmigrate 命令的参数是迁移名称,输出的结果是对应的 SQL:
python manage.py sqlmigrate books 0001
• 自动生成的表名结合应用的名称( books )和模型名的小写形式( publisher 、 book 和 author )。
• 前面说过,Django 会自动为各个表添加主键,即 id 字段。这个行为可以覆盖。按约定,Django 在外键字段的名称后面加上 "_id" 。你可能猜到了,这个行为也可以覆盖。
• 外键关系通过 REFERENCES 语句指明。
sqlmigrate 命令并不创建表,其实它根本不接触数据库,而是在屏幕上输出 Django 将执行的 SQL。如果愿意,可以把输出的 SQL 复制粘贴到数据库客户端里,然而,Django 为提交 SQL 提供了更为简单的方式
python manage.py migrate
数据的基本访问
创建模型之后,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 模型类,以便与保存出版社的数据库表交互。
• 提供各个字段的值, name 、 address ,等等,实例化一个 Publisher 对象。
• 为了把对象保存到数据库中,调用 save() 方法。Django 在背后执行 SQL INSERT 语句。
• 为了从数据库中检索出版社,使用 Publisher.objects 属性,你可以把它的值理解为全部出版社。使用 Publisher.objects.all() 获取数据库中的所有 Publisher 对象。Django 在背后执行 SQL SELECT 语句
使用 Django 模型 API 创建的对象不会自动保存,只能自己动手调用 save() 方法
为 Publisher 类添加一个名为 __str__() 的方法可改变publisher_list输出内容,如
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 __str__(self):
return self.name
插入和更新数据
>>> from books.models import Publisher
>>> p = Publisher(name='1',address='qwe',city ='bb',state_province='ca',country='usa',website='sda')
>>> p.save()
>>> p.id
1
>>> p.id = 111
>>> p.id
111
>>> p.save()
过滤数据
也可以传递多个参数
>>> Publisher.objects.filter(id=1)
<QuerySet [<Publisher: 1>]>
检索单个对象
>>> Publisher.objects.get(id=1)
<Publisher: 1>
排序数据
Publisher.objects.order_by("name")
多个字段排序(以第一个字段排不出顺序时使用第二个字段),提供多个参数:
>>> Publisher.objects.order_by("state_province", "address")
反向排序。方法是在字段名称前面加上“-”(减号):
Publisher.objects.order_by("-name")
链式查找
过滤数据同时排序数据
Publisher.objects.filter(country="U.S.A.").order_by("-name")
切片数据
只显示第一个
Publisher.objects.order_by('name')[0]
范围切片
Publisher.objects.order_by('name')[0:2]
注意,不支持使用负数:可以换成一下形式
Publisher.objects.order_by('-name')[0]
在一个语句中更新多个对象
Publisher.objects.filter(id=52).update(name='Apress Publishing')
Publisher.objects.all().update(country='USA')
删除对象
删除所有
Publisher.objects.all().delete()
删除部分
Publisher.objects.filter(country='USA').delete()