象前面章节提到的 TEMPLATE_DIRS 一样,数据库配置也是在Django的配置文件里,缺省 是 settings.py 。 打开这个文件并查找数据库配置:
DATABASES = {
'default': {
'ENGINE':'mysql',# Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'mydb', # Or path to database file if using sqlite3.
'USER': 'root', # Not used with sqlite3.
'PASSWORD': '123456', # Not used with sqlite3.
'HOST': '127.0.0.1', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '3306', # Set to empty string for default. Not used with sqlite3.
}
}
|
在“mysite”项目目录下执行python manage.py shell 来进行测试,输入下面这些命令来测试你的数据库配置:
>>> from django.db import connection
>>> cursor = connection.cursor()
如果没有显示什么错误信息,那么你的数据库配置是正确的。
一个project包含很多个Django app以及对它们的配置。技术上,project的作用是提供配置文件,比方说哪里定义数据库连接信息, 安装的app列表, TEMPLATE_DIRS ,等等。一个app是一套Django功能的集合,通常包括模型和视图,按Python的包结构的方式存在。app的一个关键点是它们是很容易移植到其他project和被多个project复用。例如,Django本身内建有一些app,例如注释系统和自动管理界面。系统对app有一个约定: 如果你使用了Django的数据库层(模型),你 必须创建一个Django app。 模型必须存放在apps中。
python manage.py startapp books
在配置文件(settings.py)中添加该app:
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',
)
|
打开由"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()
|
现在我们可以创建数据库表了。 首先,用下面的命令验证模型的有效性:
python manage.py validate
模型确认没问题了,运行下面的命令来生成 CREATE TABLE 语句(如果你使用的是Unix,那么可以启用语法高亮):
python manage.py sqlall books
sqlall 命令并没有在数据库中真正创建数据表,只是把SQL语句段打印出来,这样你可以看到Django究竟会做些什么。Django提供了一种更为简易的提交SQL语句至数据库的方法:
python manage.py syncdb
一旦你创建了模型,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.objects.create(name="0'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
[<Publisher: Publisher object>, <Publisher: Publisher object>]
|
注:上面列出了两种向数据库插入数据的方法。
当我们打印整个publisher列表时,我们没有得到想要的有用信息,无法把
[<Publisher: Publisher object>, <Publisher: Publisher object>] 里的对象区分开来,我们可以简单解决这个问题,只需要为Publisher 对象添加一个方法 __unicode__() 。 __unicode__() 方法告诉Python如何将对象以unicode的方式显示出来。 为以上三个模型添加__unicode__()方法后,就可以看到效果了:
from django.db import models
# Create your models here.
class Publisher(models.Model):
......
def __unicode__(self):
return self.name
class Author(models.Model):
......
def __unicode__(self):
return u'%s %s' %(self.first_name,self.last_name)
class Book(models.Model):
......
def __unicode__(self):
return self.title
|
>>> from books.models import Publisher
>>> publisher_list = Publisher.objects.all()
>>> publisher_list
[<Publisher: Apress>, <Publisher: 0'Reilly>]
请确保你的每一个模型里都包含 __unicode__() 方法,这不只是为了交互时方便,也是因为 Django会在其他一些地方用 __unicode__() 来显示对象。
1. 插入和更新数据:插入数据使用对象创建和save()方法或是直接调用objects.create()(见前例),接下来再调用 save() 将不会创建新的记录,而只是修改记录内容(也就是 执行 UPDATE SQL语句,而不是 INSERT 语句):
>>> p.name = 'Apress Publishing'
>>> p.save()
|
注意,这种方法并不是只更新修改过的那个字段,所有的字段都会被更新。 更改某一指定的列,我们可以调用结果集(QuerySet)对象的update()方法: 示例如下:
>>> Publisher.objects.filter(id=52).update(name='Apress Publishing')
update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录。 以下示例演示如何将所有Publisher的country字段值由’U.S.A’更改为’USA’
>>> Publisher.objects.all().update(country='USA')
2
update()方法会返回一个整型数值,表示受影响的记录条数。 在上面的例子中,这个值是2。
2. 数据过滤: 在Django API中,我们可以使用“filter()”方法对数据进行过滤:
>>> Publisher.objects.filter(name='Apress')
[<Publisher: Apress>]
|
可以传递多个参数到 filter() 来缩小选取范围:
>>> Publisher.objects.filter(country="U.S.A.", state_province="CA")
[<Publisher: Apress>]
|
注:是精确匹配的, 其他类型的查找也可以使用(在 name 和 contains 之间有双下划线。):
>>> Publisher.objects.filter(name__contains="press")
[<Publisher: Apress>]
|
这里,contains部分会被Django翻译成LIKE语句。其他的一些查找类型有:icontains(大小写无关的LIKE),startswith和endswith, 还有range(SQLBETWEEN查询)。
3. 获取单个对象:相对列表来说,有些时候我们更需要获取单个的对象,“get()”方法就是在此时使用的:
>>> Publisher.objects.get(name="Apress")
<Publisher: Apress>
|
注意:如果结果是多个对象,会导致抛出异常;如果查询没有返回结果也会抛出异常。
4.数据排序:在你的 Django 应用中,你或许希望根据某字段的值对检索结果排序,比如说,按字母顺序。 那么,使用 order_by() 这个方法就可以搞定了。
>>> Publisher.objects.order_by("name")
[<Publisher: Apress>, <Publisher: O'Reilly>]
|
如果需要以多个字段为标准进行排序(第二个字段会在第一个字段的值相同的情况下被使用到),使用多个参数就可以了,如下:
>>> Publisher.objects.order_by("state_province", "address")
[<Publisher: Apress>, <Publisher: O'Reilly>]
|
我们还可以指定逆向排序,在前面加一个减号 - 前缀:
>>> Publisher.objects.order_by("-name")
[<Publisher: O'Reilly>, <Publisher: Apress>]
|
大多数时间你通常只会对某些 字段进行排序。 在这种情况下,Django让你可以指定模型的缺省排序方式:
class Publisher(models.Model):
......
class Meta:
ordering = ['name']
|
你可以在任意一个 模型 类中使用 Meta 类,来设置一些与特定模型相关的选项。
5. 连锁查询:通常我们需要同时进行过滤和排序查询的操作。 因此,你可以简单地写成这种“链式”的形式:
>>> Publisher.objects.filter(country="U.S.A.").order_by("-name")
[<Publisher: O'Reilly>, <Publisher: Apress>]
|
6. 限制返回的数据:
>>> Publisher.objects.order_by('name')[0]
<Publisher: Apress>
|
类似的,你可以用Python的range-slicing语法来取出数据的特定子集
>>> Publisher.objects.order_by('name')[0:2]
|
注意,不支持Python的负索引(negative slicing)
6.删除对象:删除数据库中的对象只需调用该对象的delete()方法即可:
>>> p = Publisher.objects.get(name="O'Reilly")
>>> p.delete()
>>> Publisher.objects.all()
[<Publisher: Apress Publishing>]
|
同样我们可以在结果集上调用delete()方法同时删除多条记录。
>>> Publisher.objects.filter(country='USA').delete()
>>> Publisher.objects.all().delete()
>>> Publisher.objects.all()
[]
|
注意:一旦使用all()方法,所有数据将会被删除!