操作数据库通常需要你亲自动手处理SQL语句。在Django中,有很多这样的麻烦需要你小心使用Django的对象关系映射(ORM)的功能,以及如何通过Django的模型封装数据库中的表。从本质上讲,一个模型是一个Python对象,描述数据模型/表。而不是直接操作SQL访问数据库表,所有你需要做的就是操纵相应的Python对象。在这一章,我们将介绍如何设置一个数据库和Rango所需的模型。
Rango的需求
首先,我们看看Rango的数据需求。下面的列表提供了Rango数据需求的关键信息。
- Rango是一个基本的网页目录——网站含有其他网站的链接。
- 有许多不同的网页的类别,每个类别容纳许多链接。我们假设在第二章,这是一个一对多的关系。请参阅下面的实体关系图。
- 一个类别有一个名称,访问次数,和不同的喜好。
- 一个页面是指一类,有标题,URL和许多views。
Figure 1: The Entity Relationship Diagram of Rango’s two main entities.
创建你的数据库
在你创建任何models之前,需要设置数据库配置。在Django1.7中,当你创建一个工程,Django会自动创建一个目录叫DATABASES
,位于你的setting.py
文件中。具体内容如下:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
正如你所看到默认的引擎是SQLite3的编译器后端。这为我们提供了轻量级的python数据库访问,SQLite,这是伟大的发展宗旨。我们需要设置其他唯一的值是NAME
键/值对,设置为DATABASE_PATH
。对于其他数据库引擎,其他键如USER
、PASSWORD
、HOST
和PORT
也可以添加到字典。
注释
虽然本教程使用SQLite引擎是很好,当它来部署应用程序时可能也许不是最好的选择。相反,它可能是更好的使用更健壮的和可扩展的数据库引擎。Django自带开箱支持其他几个流行的数据库引擎,如PostgreSQL 和 MySQL。查看数据库引擎的官方Django文档了解更多细节。你也可以看看在SQLite网站上的优秀文章,解释了你应该和你不应该考虑使用轻量级SQLite引擎。
在setting.py
中进行数据库配置,你可以为Rango应用程序创建两个初始化数据模型。
在rango/models.py
中,我们定义两个类,两个都必须继承django.db.models.Model
。两个Python类将定义模型代表类别和页面。定义Category
和Page
模型如下:
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
def __unicode__(self): #For Python 2, use __str__ on Python 3
return self.name
class Page(models.Model):
category = models.ForeignKey(Category)
title = models.CharField(max_length=128)
url = models.URLField()
views = models.IntegerField(default=0)
def __unicode__(self): #For Python 2, use __str__ on Python 3
return self.title
当你定义一个模型,您需要指定属性及其相关类型的列表以及任何可选参数。Django提供了大量的内置字段。下面列出一些最常用的。
CharField
,用于存储字符数据(strings)。指定max_length
提供最大数量的字符字段可以存储。
URLField
,和CharField
一样,但是是用来存储URLs资源。你也可以指定max_length
参数。
IntegerField
,用来存储整数。
DateField
,用来存储Python的datetime.date
。
可以查看 Django文档模型字段来查看完整列表。
在每一个字段,你可以指定
unique
属性。如果设置为
True
,只有一个实例的一个特定的领域的值可能存在在整个数据库模型。例如,看看我们上面定义的
Category
模型。字段
name
被设置为唯一的,因此每个类别名称必须是唯一的。
如果你想使用一个特定的域作为一个附加的数据库的键,这非常有用。你也可以为每个字段指定附加属性,如如指定一个默认值(
default='value'
),一个字段的值是否可以
NULL(null=True)
或没有。
在Django中还提供了简单的机制,使我们能够涉及的模型/数据库表一起。这些机制都封装在三个字段类型,下面列出。
ForeignKey
,一个字段类型允许我们创建一对多关系;
OneToOneField
,一个字段类型允许我们定义严格一对一关系;
ManyToManyField
,一个字段类型允许我们定义多对多关系。
从上面我们的模型示例,在模型
Page
中的字段
category
是一个
ForeignKey
。允许我们在模型/表
category
中创建一对多关系,
它被指定作为参数传递给字段的构造。你应该意识到Django会自动为你在涉及到一个模型中的每个表创建一个ID字段。因此你并不需要明确地为每个模型定义一个主键 - 它为你做!
注释
当创建一个Django模型,最好的实践就是确定你创建包含__unicode()
方法-这个方法和__str__()
方法相同。如果你这两个都不熟悉,认为它们是方法类似于Java类中的toString()
方法。因此,__unicode__()
方法用于提供一个unicode表示模型的实例。我们的category
模型例如返回类别的名称在__unicode__()
方法中-当你在本章后面开始使用Django管理接口时这将会非常方便。在你调试代码时在你的类中包含__unicode__()
方法也是非常有用的。在category
模型实例分配一个__unicode
方法会返回<Category: Category object>
。我们知道这是一个分类,但是是哪一个呢?包含__unicode__()
会返回<Category: python>
,python
是一个给定的类别name
。较前更好!
创建和迁移数据库
我们的模型已经定义了。我们现在可以让Django发挥它的魔力,在我们的数据库中创建表表示。在早期版本的Django使用以下命令执行:
$ python manage.py syncdb
然而,Django的1.7提供了一个迁移工具安装和更新数据库以反映变化的模型。所以这个过程就变得有些复杂,但我们的想法是,如果你更改模型,您将能够更新数据库,而无需删除它。
配置数据库并创建超级用户
如果你还没有这样做的话,你首先需要初始数据库。这是通过迁移命令来完成。
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, contenttypes, auth, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying sessions.0001_initial... OK
注释
在Django1.8版本中,我们需要先执行python manage.py makemigrations [databasename]然后执行python manage.py migrate
错误提示
Running migrations:
No migrations to apply.
Your models have changes that are not yet reflected in a migration, and so won’t be applied.
Run ‘manage.py makemigrations’ to make new migrations, and then re-run ‘manage.py migrate’ to apply them.
如果你记得在setting.py
中有一系列INSTALLED_APPS
,这个初始调用迁移,为相关应用程序创建表auth,admin。在你的项目基本目录下有一个db.sqlite
可以被调用。
现在您需要创建一个超级用户管理数据库。运行以下命令。
$ python manage.py createsuperuser
在本教程后面超级用户帐户将被用于访问Django的管理界面。根据提示输入帐号的用户名、邮箱地址、密码。一旦完成,该脚本应该成功完成。
确保你把超级用户帐户的用户名和密码记住。
创建/更新模型/表
无论什么时候更改模型,那么你需要办理变更登记,通过makemigrations命令为修改应用程序。对于rango,我们需要执行以下命令:
$ python manage.py makemigrations rango
Migrations for 'rango':
0001_initial.py:
- Create model Category
- Create model Page
如果你查看rango/migration
文件,你会看到一个Python脚本被创建,叫0001_initial.py''
。查看这个SQL并执行数据迁移,你可以执行命令python manage.py sqlmigrate <app_name> <migration_no>
。这个迁移号显示为上面的0001,所以我们可以执行命令,python manage.py sqlmigrate rango 0001
-为rango创建执行的SQL语句。尝试一下。
现在应用这些迁移(本质上就是创建数据库表),执行以下命令:
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, rango, contenttypes, auth, sessions
Running migrations:
Applying rango.0001_initial... OK
警告
当你添加到现有模型,你需要重复执行命令 python manage.py makemigrations ,然后执行python manage.py migrate
你可能也注意到,我们的category
模型是目前所缺乏我们在Rango的要求定义的一些字段。我们会在后面更新过程中提醒你添加这些字段。
Django模型和Django Shell
在我们将注意力转向展示Django管理界面接口之前,值得注意的是,你可以对Django模型和Django Shell进行交互-用于调试是一个非常有用的帮助。我们将演示如何使用这种方法来创建Category
的实例。
进入shell,我们需要从你的Django项目root目录下再次调用manage.py
。运行以下命令:
$ python manage.py shell
这将启动Python解释器和加载对你项目的设置的一个实例。然后,您可以与模型进行交互。下面的终端会话演示了此功能。看看行内注释,以了解每个命令的作用。
# Import the Category model from the Rango application
>>> from rango.models import Category
# Show all the current categories
>>> print Category.objects.all()
[] # Returns an empty list (no categories have been defined!)
# Create a new category object, and save it to the database.
>>> c = Category(name="Test")
>>> c.save()
# Now list all the category objects stored once more.
>>> print Category.objects.all()
[<Category: test>] # We now have a category called 'test' saved in the database!
# Quit the Django shell.
>>> quit()