Part2 数据库设置

作者: shark_tear | 来源:发表于2017-12-12 23:34 被阅读0次

第一部分结束以后,我们来学习第二部分的数据库设置。这一章我们来学习怎么创建数据库模块(model)以及Django自动生成的管理站点。

数据库设置

我们先打开mysite/settings.py,这个模块就是Django中其他模块的配置参数所在的模块。默认情况下,Django使用SQLite数据库。如果你对数据库不熟悉,就只是想尝试一下Django,使用默认设置就可以了。如果你想用其他的生产数据库,例如MySQL、PostgreSQL等,可以自己去查找Django的官方文档。

编辑mysite/settings.py文件的时候,将TIME_ZONE设置为你自己的时间区域(中国默认的设置是Asia/Shanghai)。在文件的上面有一个INSTALLED_APPS设置,这个地方保存的是当前Django项目中所有需要使用到的应用名称。前面我们说到过,一个应用可以放在多个项目里,只需要将应用的目录放到对应的项目目录下,然后在这个参数里将应用的名称保存下来即可。这这个参数里还默认自带了6个应用,其作用分别是:

  • django.contrib.admin:Django自带的管理站点,后面马上就要用到
  • django.contrib.auth:Django自带的认证系统。
  • django.contrib.contenttypes:目录类型框架
  • django.contrib.sessions:Django会话框架
  • django.contrib.messages:Django消息框架
  • django.contrib.staticfiles:Django消息静态文件框架

这些应用都是作为一个通用组件包含在每一个Django项目中,在后面我们学习了更多的Django知识以后,就可以来尝试自己定制或者修改这些组件,目前还是先用默认的组件。
上面这些组件中的部分组件要使用的话,需要在数据库中创建表,因此我们首先需要在数据库中将对应的表创建出来。然后才能使用它们。创建表的命令如下:
$ python manage.py migrate
migrate命令查看INSTALLED_APPS配置,然后根据你在mysite/settings.py里的设置以及应用里的迁移配置来创建需要的数据库(我们后面来介绍数据库表)。这个命令运行过程中,你会看到很多创建表的信息,如果你对这些表感兴趣的话,可以自己登录数据库查看创建的表(需要你自己对数据库有了解)。

创建模型(model)

现在来创建你的数据库模型——简单的说,就是你的数据库布局(或者说表结构),还有一些额外的信息。
在我们的投票应用中,我们会创建两个模型,QuestionChoice。模型Question会有一个代表问题的字段和一个表示发布日期的字段。Choice会有,一个表示选择的文本字段和一个表示投票数量的字段。每个Choice都是和一个Question进行关联的。
上面的这些概念都是通过Python类来表示,编辑polls/modes.py文件,代码如下:

from django.db import models

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

代码都很简单,每个类代表一个模型。每个类都是继承自django.db.modesl.Model。每个模型都有一堆类属性,模型里的每一种属性都代表一个数据库字段。
每一个字段都是由一个Field类实例来表示的,例如CharField表示字符串字段,DateTimeField表示日期时间。通过这种方式来告知Django每种字段在数据库中的数据类型。每个Field实例的名称(例如question_textpub_date)就是数据库中字段的名称,且通常是一个对机器友好的名称(英文表示)。你可以在你的Python代码中使用这个名称,而在数据库中会作为表字段的名称。
你可以使用一个Field实例的第一个可选位置参数,来作为用户阅读起来比较友好的名称(自己所使用的语言,例如一个中文名)。如果没有给出这个参数,默认就会使用前面的表字段名。在上面的例子里, 我们只给pub_date定义了这样一个参数(date published)。对于这个模型中的其他字段,都会使用默认的字段名称。

一些Field类有一些必须的参数,例如CharField,需要你给出一个max_length参数,用来表示这个字段的长度,这个值不光用在数据库表里面,也会用在验证上,后面我们会看到这部分的内容。

一个Field也可以拥有多个可选参数,在上面的例子里,我们看到votes字段的默认值设置为0(default=0)。最后,我们看到使用Foreign Key定义了一个关联关系,这告诉Django,每一个Choice和一个Question进行关联。Django支持所有的通用数据库关联:多对一、多对多、一对一。

激活模块

上面那一小部分代码给出了大量的信息,根据这些代码,Django可以做:

  • 为这个应用创建数据库表(CREATE TABLE部分)
  • 创建一个Python数据库访问API,用来访问QuestionChoice对象。

但是我们首先需要告诉我们的项目,我们将polls应用安装到那哪里了。

Django的应用是“可插拔式”的,你可以在多个项目中使用你的应用,还可以分发应用。因为应用并不是和某个Django项目绑定的。

要在我们的项目中包含应用,我们需要添加他的配置类到INSTALLED_APPS设置里。PollsConfig类是在polls/apps.py文件里,所以它的点号路径是polls.apps.PollsConfig,编辑mysite/settings.py文件,将点号路径添加到INSTALLED_APPS配置里。如下所示:

INSTALLED_APPS = [
    'polls.apps.PollsConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

现在你的项目就知道已经包含了这个应用,下面来运行另外一个命令:
$ python manage.py makemigrations polls
你可能会看到下面的输出:

Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Choice
    - Create model Question
    - Add field question to choice

通过运行makemigrations命令,你告诉Django你需要变更一些修改到你的模型里(这个例子里是创建一个新的数据库),并且这些修改会作为一个迁移保存起来。

迁移的意思是,Django怎么将你的修改应用到模型(以及你的数据库)中,在应用到数据库之前,它们只是作为文件保存在硬盘上。如果你想的话,你也可以查看一下创建新模型的迁移代码。它保存在polls/migrations/0001_initial.py。不用担心,你不会在Django每次创建一个迁移文件的时候都去看一下这个文件。它们被设计为可以被人为编辑,只是用来在后面你想手动修改Django迁移程序的时候使用。
有一个命令用来运行迁移过程,并且自动管理你的数据库,叫做migrate,我们后面会讲到它。但是我们先来看一下迁移过程运行的SQL语句。sqlmigrate命令需要带一个迁移名称作为参数并返回迁移过程执行的SQL语句:
$ python manage.py sqlmigrate polls 0001
你可能会看到和下面相似的内容(我们为了可读性编辑了一下下面的内容):

BEGIN;
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
    "id" serial NOT NULL PRIMARY KEY,
    "choice_text" varchar(200) NOT NULL,
    "votes" integer NOT NULL
);
--
-- Create model Question
--
CREATE TABLE "polls_question" (
    "id" serial NOT NULL PRIMARY KEY,
    "question_text" varchar(200) NOT NULL,
    "pub_date" timestamp with time zone NOT NULL
);
--
-- Add field question to choice
--
ALTER TABLE "polls_choice" ADD COLUMN "question_id" integer NOT NULL;
ALTER TABLE "polls_choice" ALTER COLUMN "question_id" DROP DEFAULT;
CREATE INDEX "polls_choice_7aa0f6ee" ON "polls_choice" ("question_id");
ALTER TABLE "polls_choice"
  ADD CONSTRAINT "polls_choice_question_id_246c99a640fbbd72_fk_polls_question_id"
    FOREIGN KEY ("question_id")
    REFERENCES "polls_question" ("id")
    DEFERRABLE INITIALLY DEFERRED;

COMMIT;

注意下面的内容:

  • 额外的输出依赖于你使用的数据库,上面的实例是PostgreSQL生成的。
  • 表名是根据应用名称(polls)和模型名称的小写(questionchoice)的组合自动生成的(你可以覆盖这种特性,后面学习数据库的定制时再看这个内容)
  • 主键(ID)是自动添加的(你也可以覆盖这个特性,即自定义主键)
  • 根据惯例,Django会添加_id到外键字段名上面去(当然,你也可以修改这个)
  • 外键关联是通过FOREIGN KEY约束显式定义的,不需要担心DEFERRABLE部分。这只是告诉PostgreSQL在结束事务之前不要执行外键。
  • 它是为你正在使用的数据库定制的,所以数据库特定的字段类型,例如auto_increment(MySQL)serial(PostgreSQL),或者integer primary key autoincrement(SQLite)都会为你自动处理。也适用于引号括起来的字段名称,例如双引号或单引号括起来的。
  • sqlmigrate命令不会在你的数据库上实际运行迁移操作。只是把SQL语句打印到屏幕上面,让你看到Django认为需要什么SQL语句。对于检查Django会做什么,或者你是数据库管理员,需要修改SQL脚本的时候,非常有用。

如果你感兴趣,可以运行python manage.py check,这个命令会检查你项目中可能出现的任何问题,而不会执行迁移过程或者创建数据库。

现在,再次运行migrate命令创建模型表到你的数据库里面:

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Rendering model states... DONE
  Applying polls.0001_initial... OK

migrate命令会取得所有未执行的迁移命令(Django会将这些未执行的命令保存到你的数据库里一个特殊的表里,表名是django_migrations),然后在你的数据库上运行这些命令。实际上就是将你在模型上的修改同步到你的数据库里。

迁移这个功能是非常强大的,让你在开发项目的时候随着时间的改变来修改你的模型,而不需要删除你的数据库、表或者新建一个新的数据库或者表。它专门用来升级你的数据库而不会丢失数据。我们会在这个教程后面部分更深入讲解这部分功能,但是现在,我们只需要记住下面这3步来修改模型:

  • 修改你的模型(在models.py里面);
  • 运行python manage.py makemigrations appname创建这些用于修改的迁移命令;
  • 运行python manage.py migrate来应用这些修改到你的数据库里面。
    使用分开的命令来执行迁移过程是因为,你需要提交迁移过程到你的版本控制系统里面,然后同步到你的应用上。这不光是方便你开发,更是方便项目中的其他开发者。

使用API

现在,让我们在交互式的Python shell里面使用一下Django提供给我们的免费API。要调用Python shell,使用下面的命令:
$python manage.py shell
我们使用这个命令来替代简单的python,因为manage.py设置了DJANGO_SETTINGS_MODULE环境变量,这个变量保存的是你的mysite/settings.py文件在Python中的导入路径。

当你在shel里的时候,我们来尝试一下数据库API:

>>> from polls.models import Question, Choice   #插入我们刚才写的类名

# 系统里现在还没有Question
>>> Question.objects.all()
<QuerySet []>

# 创建一个新的Question.
# 在配置文件里对时区的支持默认是开启的,所以Django希望pub_date是一个带tzinfo属性
# 的时间信息。使用timezone.now()来替代datetime.datetime.now(),这个函数会进行正确的设置
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())

# 保存对象到数据库中,你需要显示调用save()方法
>>> q.save()

# 现在它有了一个ID
>>> q.id
1

# 通过Python属性访问模型字段值
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

# 通过修改属性来修改字段值,然后调用save()方法保存到数据库
>>> q.question_text = "What's up?"
>>> q.save()

# objects.all() 显示数据库中的所有question
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>

稍等一下,<Question: Question object (1)>并不是这个对象一个有效的表示。让我们来编辑Question模型(在polls/models.py)来修复这个问题。添加一个str()方法到Question和Choice里面。

from django.db import models

class Question(models.Model):
    # ...
    def __str__(self):
        return self.question_text

class Choice(models.Model):
    # ...
    def __str__(self):
        return self.choice_text

添加str()方法到你的模型里面是非常重要的,不仅在交互式窗口中处理的时候非常方便,也因为对象的表示信息会用在Django自动生成的管理站点里面 。
要注意有很多普通的Python方法, 我们添加一个常用的方法用来展示:

import datetime

from django.db import models
from django.utils import timezone


class Question(models.Model):
    # ...
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

注意,额外添加的import datetimefrom django.utils import timezone,分别用来引用Python的标准datetime模块,和Django在django.utils.timezone里的时区关联工具。如果你对Python中的时区处理不是很熟悉,建议你去学习一下相关知识。

保存这些更改,然后重新启动一个python shell窗口:

>>> from polls.models import Question, Choice

# Make sure our __str__() addition worked.
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>

# Django通过关键字参数提供丰富的数据库查询API
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>

# 取出今年发布的question
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>

# 请求一个不存在的ID,会报出一个异常错误
>>> Question.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Question matching query does not exist.

# 通过主键查询是最通用的示例,所以Django提供一个主键查询的简写
# 下面的示例和Question.objects.get(id=1)完全相同
>>> Question.objects.get(pk=1)
<Question: What's up?>

# 确定我们的定制方法生效
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True

# 给Question生成很多Choices. INSERT声明中的create调用,会创建一个新的Choice
# 对象,将这个choice添加到可用的choices集合中,并且返回这个新的Choice对象
# Django创建一个集合来保存外键关联的“另外一边” (例如question的choice),也
# 可以通过API来访问
>>> q = Question.objects.get(pk=1)

# 显示关联的对象集合中的任何choices——目前为止还一个都没有
>>> q.choice_set.all()
<QuerySet []>

# 创建3个choices.
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)

# Choice对象有API来访问它们关联的Question对象
>>> c.question
<Question: What's up?>

# 反过来: Question 对象访问 Choice 对象
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3

# API 会自动跟踪你需要的关系,使用双下划线来分开关联。这个可以查到你想要
# 的任何深度,没有任何限制。
# 找出pub_date在今年的任何Choices (重新使用我们上面创建的 'current_year' 变量).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

# 删除其中一个choices. 使用delete()方法。
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

数据库API的更多知识,建议查询Django的官方文档

介绍Django Admin

创建一个管理员用户

首先我们需要创建一个可以登录管理站点的用户,运行下面的命令:
$ python manage.py createsuperuser
输入你想到的用户名然后按enter:
Username: admin
然后会要求你输入email地址:
Email address: admin@example.com
最后一步会要求你输入admin的密码,会要求你输入两次。

Password: **********
Password (again): *********
Superuser created successfully.
启动开发服务器

Django的管理站点默认已经启用了,我们启动开发服务器来看一下,打开浏览器,输入管理站点的地址:http://localhost:8000/admin,或者将localhost替换成你的虚拟机IP地址,会看到下面的管理页面:

image.png
如果你在mysite/settings.py文件里将translation设置打开了,并且你自己的浏览器设置为你自己的语言,那么显示的管理站点页面可能就是你本地语言。
进入管理站点

输入刚才第一步配置好的账号密码,然后点击登录,就能进入到管理站点,会看到下面的内容:


image.png

可以看到几个能够编辑的内容,例如groups和users,这些是django.contrib.auth提供的,就是前面说的由Django提供的认证模块。

让投票应用可以在admin里面修改

但是我们的投票应用在哪呢,并没有在admin的主页上面显示出来。这是因为我们还需要再做一件事,告诉admin,Question由一个admin接口。要做这个,我们打开polls/admin.py文件。然后编辑它,内容如下所示:

from django.contrib import admin

from .models import Question

admin.site.register(Question)
探索免费的管理功能

上面我们将Question类注册到了admin站点,Django就知道怎么在站点上显示这个内容,如下所示:

image.png
点击Questions,然后可以看到Question的修改列表。这个页面显示出数据库中所有的Question实例,让你可以选择其中的Question,并对它们进行操作。我们可以看到刚才创建的"What's new" Question:
image.png
点击进去就可以看到这个问题的编辑页面:
image.png
这里要注意的一些事情:
  • 表单是由Question模型自动创建的
  • 不同的模型字段类型(DateTimeFieldCharField)和不同的HTML插件对应。每种类型的字段都知道怎么在Django admin里展示自己。
  • 每一个DateTimeField获得一个免费的JS图标,Dates有一个Today图标和日历弹出菜单。Times有一个Now图标和一个显示通用时间的弹出式菜单。

页面的顶部给了很多选项:

  • Save - 保存变更并且返回到对象类型的列表页面
  • Save and continue editing - 保存变更,然后重新加载这个对象的管理页面
  • Save and another - 保存变更,然后重新加载相同对象的一个新的、空白的表单;
  • Delete - 显示一个删除确认页面。

如果你在第一jie创建question的时候Date published的值和时间不匹配,意味着你可能忘了正确设置TIME_ZONE的值。修改它,然后重新加载页面,正确的值就会出现。

通过点击Today和Now图标来修改发布日期,然后点“Save and continue editing”,再点击右上方的“History”,就会看到这个对象的编辑历史。可以看到编辑的用户和编辑的时间:


image.png

上面就是设置数据库、创建数据库模型、使用数据库对象、使用管理站点的所有内容。如果你对上面的这些内容熟悉以后,就可以查看第三部分,为应用添加更多的视图。

相关文章

  • Part2 数据库设置

    第一部分结束以后,我们来学习第二部分的数据库设置。这一章我们来学习怎么创建数据库模块(model)以及Django...

  • PS制作数据APP界面

    PART1:首先是展示效果图 PART2:创建文件、设置背景 步骤一:文件-新建-进行下面设置。 步骤2:从工具栏...

  • DataGrip 导入导出数据库设置

    [TOC] 导入导出数据库设置 导出数据库设置 选中想要导出数据设置 呼出热键命令 cmd+shift+a 输入 ...

  • mysql简单实用命令

    数据库结构相关SQL语句 创建数据库 查看当前数据库编码集 查看全局编码 快速的设置client端编码集(临时设置...

  • Django学习(二)- 模型

    1. 数据库设置 系统默认的数据库是SQLite,但是如果你想使用其他的数据库也可以在设置里面更改数据库配置信息 ...

  • centos7.3配置LAMP BY yum

    实验环境: 1、安装apache 启动apache服务、设置httpd服务开机启动、 数据库安全设置,(数据库ro...

  • 小程序--数据库

    如何修改数据库权限选中数据库==>权限设置即可。。。。

  • Django 常规使用设置

    1. 数据库的设置 Django默认有自带的数据库,当需要用其他数据库时需要修改设置,这里用MySQL示范首先确认...

  • 如何查看leveldb的数据库内容

    如何访问leveldb的数据库内容 当fabric的状态数据库设置为leveldb的时候(也是缺省设置),那么状态...

  • navicat连接oracle很卡

    navicat数据库工具,连接数据库时自动断开连接解决办法(设置发送心跳数据) 这是因为数据库服务器设置了连接多久...

网友评论

    本文标题:Part2 数据库设置

    本文链接:https://www.haomeiwen.com/subject/juvwixtx.html