《Tango with Django》-第5章 模型与数据库

在 Django 中,查询底层数据库这项操作由对象关系映射器(Object Relational Mapper,ORM)负责。在 ORM 中,存储在一个数据库表中的数据封装为一个模型。模型则是描述数据库表中数据的 Python 对象。Django 不直接通过 SQL 查询数据库,而是使用相应的 Python 模型对象操纵。

5.1 Rango 的要求

在这里插入图片描述

5.2 设置数据库

创建模型之前要设置数据库。新建项目时,Django 已经自动在 settings.py 模块中添加了 DATABASES变量,其值类似下面这样:

DATABASES = {
    
    
    'default': {
    
    
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

对 Rango 应用来说,使用默认值基本就行了。可以看到,default 数据库由一个轻量级数据库引擎驱动,即 SQLite(见 ENGINE 键)。NAME 键的值是数据库文件的路径,默认为 Django 项目根目录中的 db.sqlite3。

5.3 创建模型

什么是模型

  • 模型:
    模型准确且唯一的描述了数据。它包含您储存的数据的重要字段和行为。一般来说,每一个模型都映射一张数据库表。
  • 基础:
    每个模型都是一个 Python 的类,这些类继承 django.db.models.Model
    模型类的每个属性都相当于一个数据库的字段。
    利用这些,Django 提供了一个自动生成访问数据库的 API。

创建模型

在 settings.py 模块中配置好数据库之后,下面创建 Rango 应用所需的两个数据模型。Django 应用的模型保存在应用目录中的 models.py 模块里。因此,Rango 应用的模型保存在 rango/models.py文件中。
我们要定义两个类,一个类对应一个模型。这两个类都要继承基类django.db.models.Model,分别表示分类和网页。参照下述代码片段定义 Category 和 Page 模型。
在我们定义的模型中,Page 模型中的 category 字段是 ForeignKey 类型。我们在字段的构造方法中指定,与 Category 模型建立一对多关系。

from django.db import models

# Create your models here.
class Category(models.Model):
    name = models.CharField(max_length=128,unique=True)

    def __str__(self):
        return self.name


class Page(models.Model):
    category = models.ForeignKey(Category,on_delete=models.CASCADE)
    title = models.CharField(max_length=128)
    url = models.URLField()
    views = models.IntegerField(default=0)

    def __str__(self):
        return self.title

5.4 创建和迁移数据库

设置

首先,数据库必须预置,即创建数据库及相关的表。请打开终端或命令提示符,进入项目的根目录(manage.py 文件所在的目录),执行下述命令。
执行这个命令后,项目中安装的所有应用都会更新各自的数据库表。这个命令执行完毕后,Django 项目的根目录中会出现 db.sqlite3 文件。

python manage.py migrate

在这里插入图片描述

创建一个超级用户(superuser),用于管理数据库。执行下述命令:

python manage.py createsuperuser

在这里插入图片描述

创建和更新模型/表

每次修改应用的模型都要通过 manage.py 中的 makemigrations 命令登记改动。在 Django 项目的根目录中执行下述命令,指明目标为 rango 应用:
上述命令执行完毕后,rango/migrations 目录中会出现一个 Python 脚本,名为 0001_initial.py。这个脚本中包含此次迁移创建数据库模式所需的一切信息。

python manage.py makemigrations rango

在这里插入图片描述

创建好迁移后,要提交到数据库。为此要再次执行 migrate 命令。

python manage.py migrate

在这里插入图片描述

5.5 Django 模型和 shell

下面说明如何在 shell 中创建 Category 实例。为了打开 shell,我们要再次在项目的根目录中运行 manage.py 脚本。执行下述命令:

python manage.py shell

# 从 Rango 应用中导入 Category 模型
from rango.models import Category
# 显示目前的所有分类
print(Category.objects.all())
<QuerySet []> # Django 1.10 的输出:一个空 QuerySet 对象
# 创建一个分类对象,存入数据库
c = Category(name="Test")
c.save()
# 再次列出所有分类对象
print(Category.objects.all())
<QuerySet [<Category: Test>] # Django 1.10
# 退出 Django shell
quit()

*不执行这一步,后面的填充数据将会报错Class ‘Category’ has no ‘objects’ member

5.6 配置管理界面

执行下述命令,启动 Django 开发服务器:

python manage.py runserver

然后打开 Web 浏览器,访问 http://127.0.0.1:8000/admin/。你会看到登录界面。
在这里插入图片描述
在这里插入图片描述
看起来不错,但是没有 Rango 应用的 Category 和 Page 模型。为了显示这两个模型,我们要给Django 一些提示。打开 rango/admin.py 文件,注册想在管理界面显示的类。下述代码注册 Category 和 Page 两个类。

from django.contrib import admin
from rango.models import Category, Page

admin.site.register(Category)
admin.site.register(Page)

在这里插入图片描述

Meta 类

管理界面中有拼写错误(应该是 Categories,而不是 Categorys)?为了修正这
个错误,可以在模型定义中添加嵌套的 Meta 类,在里面声明 verbose_name_plural 属性。下面是rango/models.py修改后的 Category 模型。

class Category(models.Model):
    name = models.CharField(max_length=128,unique=True)

    class Meta:
        verbose_name_plural = 'Categories'

    def __str__(self):
        return self.name

5.7 编写一个填充脚本

下面为 Rango 应用编写一个填充脚本。在 Django 项目的根目录中新建一个 Python 文件,命名为populate_rango.py,写入下述代码:

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','tango_with_django_project_v1.settings')

import django
django.setup()
from rango.models import Category,Page

def populate():
    # 首先创建一些字典,列出想添加到各分类的网页
    # 然后创建一个嵌套字典,设置各分类
    # 这么做看起来不易理解,但是便于迭代,方便为模型添加数据

    python_pages = [
        {
    
    "title": "Official Python Tutorial",
        "url":"http://docs.python.org/2/tutorial/"},
        {
    
    "title":"How to Think like a Computer Scientist",
        "url":"http://www.greenteapress.com/thinkpython/"},
        {
    
    "title":"Learn Python in 10 Minutes",
        "url":"http://www.korokithakis.net/tutorials/python/"}]

    django_pages = [
        {
    
    "title":"Official Django Tutorial",
        "url":"https://docs.djangoproject.com/en/1.9/intro/tutorial01/"},
        {
    
    "title":"Django Rocks",
        "url":"http://www.djangorocks.com/"},
        {
    
    "title":"How to Tango with Django",
        "url":"http://www.tangowithdjango.com/"}]

    other_pages = [
        {
    
    "title":"Bottle",
        "url":"http://bottlepy.org/docs/dev/"},
        {
    
    "title":"Flask",
        "url":"http://flask.pocoo.org"}]

    cats = {
    
    "Python": {
    
    "pages": python_pages},
        "Django": {
    
    "pages": django_pages},
        "Other Frameworks": {
    
    "pages": other_pages}}

    # 下述代码迭代 cats 字典,添加各分类,并把相关的网页添加到分类中
    for cat,cat_data in cats.items():
        c = add_cat(cat)
        for p in cat_data["pages"]:
            add_page(c,p["title"],p["url"])

    # 打印添加的分类
    for c in Category.objects.all():
        for p in Page.objects.filter(category=c):
            print("-{0}-{1}".format(str(c),str(p)))

def add_page(cat,title,url,views=0):
    p = Page.objects.get_or_create(category=cat,title=title)[0]
    p.url = url
    p.views = views
    p.save()
    return p

def add_cat(name):
    c = Category.objects.get_or_create(name=name)[0]
    c.save()
    return c

if __name__ == '__main__':
    print("Starting Rango population script...")
    populate()
    

5.8 基本流程

设置数据库

新建项目后应该告诉 Django 你想用什么数据库(settings.py 模块中的 DATABASES 设置)。此外,
还可以在 admin.py 模块中注册模型,以便在管理界面中管理。

添加模型

添加模型的过程可以分为以下 5 步。
➊ 首先在 Django 应用的 models.py 文件中定义模型。
➋ 更新 admin.py,注册新增的模型。
➌ 生成迁移:python manage.py makemigrations <app_name>。
➍ 运行迁移:python manage.py migrate。在数据库中创建模型所需的表和字段。
➎ 创建或编辑填充脚本。

有时你可能想删除数据库,重头再来。

具体步骤如下。注意,本书使用的是 SQLite 数据库,此外Django 还支持其他数据库引擎。
➊ 如果 Django 开发服务器正在运行,停止。
➋ 如果使用的是 SQLite 数据库,删除 Django 项目根目录中的 db.sqlite3 文件。这个文件与manage.py 脚本位于同一级目录中。
➌ 如果修改过应用的模型,执行 python manage.py makemigrations <app_name> 命令,记得把<app_name> 替换成 Django 应用的名称(例如 rango。)如果未修改模型,跳过这一步。
➍ 执行 python manage.py migrate 命令,新建数据库文件(使用 SQLite 的话),并创建数据库表。
➎ 执行 python manage.py createsuperuser 命令,创建一个超级用户。
➏ 最后,运行填充脚本,在新数据库中插入可信的测试数据。

练习题

❏ 更新 Category 模型,加上 views 和 likes 字段,二者的默认值均是零。
rango/models.py

class Category(models.Model):
    name = models.CharField(max_length=128,unique=True)
    views = models.IntegerField(default=0)
    likes = models.IntegerField(default=0)

    class Meta:
        verbose_name_plural = 'Categories'

    def __str__(self):
        return self.name

❏ 创建迁移,然后执行,提交此次改动。
在这里插入图片描述
❏ 更新填充脚本,把“Python”分类的查看次数设为 128、点赞次数设为 64,把“Django”分类的查看次数设为 64、点赞次数设为 32,把“Other Frameworks”分类的查看次数设为 32、点赞次数设为 16。

  • rango/models.py
class Category(models.Model):
    name = models.CharField(max_length=128,unique=True)
    views = models.IntegerField(default=0)
    likes = models.IntegerField(default=0)

    class Meta:
        verbose_name_plural = 'Categories'

    def __str__(self):
        return self.name
  • populate_rango.py
def add_cat(name,views,likes):
    c = Category.objects.get_or_create(name=name)[0]
    c.views = views
    c.likes = likes
    c.save()
    return c
  • populate_rango.py
def populate():
    cats = {
    
    "Python": {
    
    "pages": python_pages,'views':128,'likes':64},
        "Django": {
    
    "pages": django_pages,'views':64,'likes':32},
        "Other Frameworks": {
    
    "pages": other_pages,'views':32,'likes':16}}
  • populate_rango.py
def populate():
    # 下述代码迭代 cats 字典,添加各分类,并把相关的网页添加到分类中
    for cat,cat_data in cats.items():
        c = add_cat(cat,cat_data['views'],cat_data['likes'])
        for p in cat_data["pages"]:
            add_page(c,p["title"],p["url"])

❏ 删除数据库,然后重新创建,再使用填充脚本填充数据。

  • 如果使用的是 SQLite 数据库,删除 Django 项目根目录中的 db.sqlite3 文件。这个文件与manage.py 脚本位于同一级目录中。
    在这里插入图片描述
  • 如果修改过应用的模型,执行 python manage.py makemigrations <app_name> 命令,记得把<app_name> 替换成 Django 应用的名称(例如 rango。)如果未修改模型,跳过这一步。
    在这里插入图片描述
  • 执行 python manage.py migrate 命令,新建数据库文件(使用 SQLite 的话),并创建数据库表。
    在这里插入图片描述
  • 执行 python manage.py createsuperuser 命令,创建一个超级用户。
    在这里插入图片描述
  • 最后,运行填充脚本,在新数据库中插入可信的测试数据。
    在这里插入图片描述
    ❏ 阅读 Django 官方教程的第二部分和第七部分。这两部分能巩固本章所学的数据库处理知识,还涉及一些定制 Django 管理界面的技术。
    ❏ 定制管理界面,访问 Page 模型时显示网页的分类、名称和 URL,就像图 5-5 那样。你要做完前一题才知道怎么解答这一题。
  • rango/admin.py
from django.contrib import admin
from rango.models import Category, Page
# Register your models here.

class PageAdmin(admin.ModelAdmin):
    list_display = ('title','category','url')

admin.site.register(Category)
#admin.site.register(Page)
admin.site.register(Page,PageAdmin)

小结

  1. category = models.ForeignKey(Category,on_delete=models.CASCADE)
  2. python manage.py createsuperuser此界面密码是看不到的,但可输入。
  3. shell 中创建 Category 实例。不执行这一步,后面的填充数据将会报错Class ‘Category’ has no ‘objects’ member

猜你喜欢

转载自blog.csdn.net/m0_46629123/article/details/112156259