• 模型——数据库(一)


    模型——数据库(一)

    实验简介

    之前,我们讲述了用 Django 建造网站的基本途径: 建立视图和 URLConf 。 正如我们所阐述的,视图负责处理一些主观逻辑,然后返回响应结果。 作为例子之一,我们的主观逻辑是要计算当前的日期和时间。

    在当代Web应用中,主观逻辑经常牵涉到与数据库的交互。数据库驱动网站 在后台连接数据库服务器,从中取出一些数据,然后在 Web 页面用漂亮的格式展示这些数据。 这个网站也可能会向访问者提供修改数据库数据的方法。

    许多复杂的网站都提供了以上两个功能的某种结合。 例如 Amazon.com 就是一个数据库驱动站点的良好范例。 本质上,每个产品页面都是数据库中数据以 HTML格式进行的展现,而当你发表客户评论时,该评论被插入评论数据库中。

    由于先天具备 Python 简单而强大的数据库查询执行方法,Django 非常适合开发数据库驱动网站。 本章深入介绍了该功能: Django 数据库层。

    注意: 尽管对 Django 数据库层的使用并不特别强调这点,但是我们还是强烈建议您掌握一些数据库和 SQL 原理。 对这些概念的介绍超越了本书的范围,但就算你是数据库方面的菜鸟,我们也建议你继续阅读。 你也许能够跟上进度,并在学习过程中掌握一些概念。

    一、数据库配置

    记住这些理念之后,让我们来开始 Django 数据库层的探索。 首先,我们需要做些初始配置;我们需要告诉Django使用什么数据库以及如何连接数据库。

    我们假定你已经完成了数据库服务器的安装和激活,并且已经在其中创建了数据库(例如,用 CREATE DATABASE 语句)。 如果你使用SQLite,不需要这步安装,因为SQLite使用文件系统上的独立文件来存储数据。

    像前面章节提到的 TEMPLATE_DIRS 一样,数据库配置也是在Django的配置文件里,缺省 是 settings.py 。 打开这个文件并查找数据库配置:

    7-1-1.png

    ENGINE:告诉Django使用哪个数据库引擎。 如果你在 Django 中使用数据库,直接在django.db.backends.后面加上对应的数据库名,如下:

    设置数据库所需适配器
    postgresql PostgreSQL psycopg 1.x版, http://www.djangoproject.com/r/python-pgsql/1/
    postgresql_psycopg2 PostgreSQL psycopg 2.x版, http://www.djangoproject.com/r/python-pgsql/
    mysql MySQL MySQLdb , http://www.djangoproject.com/r/python-mysql/
    sqlite3 SQLite 如果使用Python 2.5+则不需要适配器。 否则就使用 pysqlite , http://www.djangoproject.com/r/python-sqlite/
    oracle Oracle cx_Oracle , http://www.djangoproject.com/r/python-oracle/

    要注意的是无论选择使用哪个数据库服务器,都必须下载和安装对应的数据库适配器。 访问“所需适配器”一栏中的链接,可通过互联网免费获取这些适配器。 如果你使用Linux,你的发布包管理系统会提供合适的包。 比如说查python-postgresql或者python-psycopg的软件包。

    配置示例(mysql):

    ENGINE: 'django.db.backends.mysql'
    

    NAME 将数据库名称告知 Django 。 例如:

    NAME: 'mydb'
    

    如果使用 SQLite,请对数据库文件指定完整的文件系统路径。 例如:

    NAME: '/home/django/mydata.db'
    

    在这个例子中,我们将SQLite数据库放在/home/django目录下,你可以任意选用最合适你的目录。

    USER告诉 Django 用哪个用户连接数据库。 例如: 如果用SQLite,空白即可。

    PASSWORD告诉Django连接用户的密码。 SQLite 用空密码即可。

    HOST告诉 Django 连接哪一台主机的数据库服务器。 如果数据库与 Django 安装于同一台计算机(即本机),可将此项保留空白。 如果你使用SQLite,此项留空。

    PORT是这个数据库使用的端口号,对于mysql不填写的话,默认为3306;使用sqlite3不填写。

    此处的 MySQL 是一个特例。 如果使用的是 MySQL 且该项设置值由斜杠( '/' )开头,MySQL 将通过 Unix socket 来连接指定的套接字,例如:

    HOST: '/var/run/mysql'
    

    一旦在输入了那些设置并保存之后应当测试一下你的配置。 我们可以在mysite项目目录下执行上章所提到的python manage.py shell来进行测试。 (我们上一章提到过在,manager.py shell命令是以正确Django配置启用Python交互解释器的一种方法。 这个方法在这里是很有必要的,因为Django需要知道加载哪个配置文件来获取数据库连接信息。)

    输入下面这些命令来测试你的数据库配置,以mysql数据库为例,首先用sudo service mysql start命令启动mysql,然后进入数据库并创建一个mysite数据库(mysql用户root密码为空,直接回车即可):

    $ sudo service mysql start
    $ mysql -uroot
    > create database mysite
    

    配置好settings.py的DATABASES,如上面的图所示,最后在python manager.py shell中运行下面代码:

    >>> from django.db import connection
    >>> cursor = connection.cursor()
    

    如果没有显示什么错误信息,那么你的数据库配置是正确的。 否则,你就得 查看错误信息来纠正错误。

    二、第一个应用程序

    你现在已经确认数据库连接正常工作了,让我们来创建一个Django app包含模型,视图和Django代码,并且形式为独立Python包的完整Django应用。

    在这里要先解释一些术语,初学者可能会混淆它们。 在第二章我们已经创建了 project , 那么 project 和 app 之间到底有什么不同呢?它们的区别就是一个是配置另一个是 代码:

    一个project包含很多个Django app以及对它们的配置。

    技术上,project的作用是提供配置文件,比方说哪里定义数据库连接信息, 安装的app列表, TEMPLATE_DIRS ,等等。

    一个app是一套Django功能的集合,通常包括模型和视图,按Python的包结构的方式存在。

    例如,Django本身内建有一些app,例如注释系统和自动管理界面。 app的一个关键点是它们很容易移植到其他project和被多个project复用。

    对于如何架构Django代码并没有快速成套的规则。 如果你只是建造一个简单的Web站点,那么可能你只需要一个app就可以了; 但如果是一个包含许多不相关的模块的复杂的网站,例如电子商务和社区之类的站点,那么你可能需要把这些模块划分成不同的app,以便以后复用。

    虽然,你可以不用创建app,就能使用views,这一点已经被我们之前编写的视图函数的例子证明了 。 在那些例子中,我们只是简单的创建了一个称为views.py的文件,编写了一些函数并在URLconf中设置了各个函数的映射。 这些情况都不需要使用apps。

    但是,系统对app有一个约定: 如果你使用了Django的数据库层(模型),你必须创建一个Django app。 模型必须存放在apps中。 因此,为了开始建造 我们的模型,我们必须创建一个新的app。

    在mysite项目文件下输入下面的命令来创建名叫books的app:

    python manage.py startapp books
    

    这个命令并没有输出什么,它只在 mysite 的目录里创建了一个 books 目录。 让我们来看看这个目录的内容:

    7-1-2.png

    这个目录包含了这个app的模型和视图。

    使用你最喜欢的文本编辑器查看一下models.py和views.py文件的内容。 它们都是空的,除了models.py 里有一个 import。这就是你Django app的基础。

    三、第一个模型

    我们把注意力放在一个基本的书籍/作者/出版商的数据库结构上。 我们这样做是因为 这是一个众所周知的例子,很多SQL有关的书籍也常用这个举例。

    我们来假定下面的这些概念、字段和关系:

    • 一个作者有姓,有名及email地址。

    • 出版商有名称,地址,所在城市、省,国家,网站。

    • 书籍有书名和出版日期。 它有一个或多个作者(和作者是多对多的关联关系[many-to-many]), 只有一个出版商(和出版商是一对多的关联关系[one-to-many],也被称作外键[foreign key])

    第一步是用Python代码来描述它们。打开由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()
    

    让我们来快速讲解一下这些代码的含义。 首先要注意的事是每个数据模型都是django.db.models.Model的子类。它的父类 Model 包含了所有必要的和数据库交互的方法,并提供了一个简洁漂亮的定义数据库字段的语法。 信不信由你,这些就是我们需要编写的通过Django存取基本数据的所有代码。

    每个模型相当于单个数据库表,每个属性也是这个表中的一个字段。 属性名就是字段名,它的类型(例如 CharField )相当于数据库的字段类型 (例如 varchar )。例如, Publisher 模块等同于下面这张表(用PostgreSQL的 CREATE TABLE 语法描述):

    CREATE TABLE "books_publisher" (
        "id" serial NOT NULL PRIMARY KEY,
        "name" varchar(30) NOT NULL,
        "address" varchar(50) NOT NULL,
        "city" varchar(60) NOT NULL,
        "state_province" varchar(30) NOT NULL,
        "country" varchar(50) NOT NULL,
        "website" varchar(200) NOT NULL
    );
    

    事实上,正如过一会儿我们所要展示的,Django 可以自动生成这些 CREATE TABLE 语句。

    “每个数据库表对应一个类”这条规则的例外情况是多对多关系。 在我们的范例模型中, Book 有一个 多对多字段 叫做 authors 。 该字段表明一本书籍有一个或多个作者,但 Book 数据库表却并没有 authors 字段。 相反,Django创建了一个额外的表(多对多连接表)来处理书籍和作者之间的映射关系。

    更多模型的操作,来自官方文档

    最后需要注意的是,我们并没有显式地为这些模型定义任何主键。 除非你单独指明,否则Django会自动为每个模型生成一个自增长的整数主键字段,每个Django模型都要求有单独的主键。

    1. 模型安装

    完成这些代码之后,现在让我们在数据库中创建这些表。 要完成该项工作,第一步是在 Django 项目中 激活 这些模型。 将 books app 添加到配置文件的已安装应用列表中即可完成此步骤。

    再次编辑 settings.py 文件, 找到 INSTALLED_APPS 设置。 INSTALLED_APPS 告诉 Django 项目哪些 app 处于激活状态。 缺省情况下如下所示:

    7-1-3.png

    把这四个设置前面加#临时注释起来。 (这四个app是经常使用到的,我们将在后续章节里讨论如何使用它们)。同时,注释掉MIDDLEWARE_CLASSES的默认设置条目,因为这些条目是依赖于刚才我们刚在INSTALLED_APPS注释掉的apps。 然后,添加mysite.books 到INSTALLED_APPS的末尾,此时设置的内容看起来应该是这样的:

    7-1-4.png

    (就像我们在上一章设置TEMPLATE_DIRS所提到的逗号,同样在INSTALLED_APPS的末尾也需添加一个逗号,因为这是个单元素的元组。 另外,本书的作者喜欢在 每一个 tuple元素后面加一个逗号,不管它是不是 只有一个元素。 这是为了避免忘了加逗号,而且也没什么坏处。)

    'mysite.books'指示我们正在编写的books app。 INSTALLED_APPS 中的每个app都使用 Python的路径描述,包的路径,用小数点“.”间隔。

    现在我们可以创建数据库表了。 首先,用下面的命令验证模型的有效性:

    python manage.py validate
    

    validate命令检查你的模型的语法和逻辑是否正确。 如果一切正常,你会看到0 errors found消息。如果出错,请检查你输入的模型代码。 错误输出会给出非常有用的错误信息来帮助你修正你的模型。

    一旦你觉得你的模型可能有问题,运行python manage.py validate。 它可以帮助你捕获一些常见的模型定义错误。

    模型确认没问题了,运行下面的命令来生成 CREATE TABLE 语句(如果你使用的是Unix,那么可以启用语法高亮):

    python manage.py sqlall books
    

    在这个命令行中, books 是app的名称。 和你运行 manage.py startapp 中的一样。执行之后,输出如下:

    BEGIN;
    CREATE TABLE "books_publisher" (
        "id" serial NOT NULL PRIMARY KEY,
        "name" varchar(30) NOT NULL,
        "address" varchar(50) NOT NULL,
        "city" varchar(60) NOT NULL,
        "state_province" varchar(30) NOT NULL,
        "country" varchar(50) NOT NULL,
        "website" varchar(200) NOT NULL
    )
    ;
    CREATE TABLE "books_author" (
        "id" serial NOT NULL PRIMARY KEY,
        "first_name" varchar(30) NOT NULL,
        "last_name" varchar(40) NOT NULL,
        "email" varchar(75) NOT NULL
    )
    ;
    CREATE TABLE "books_book" (
        "id" serial NOT NULL PRIMARY KEY,
        "title" varchar(100) NOT NULL,
        "publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id") DEFERRABLE INITIALLY DEFERRED,
        "publication_date" date NOT NULL
    )
    ;
    CREATE TABLE "books_book_authors" (
        "id" serial NOT NULL PRIMARY KEY,
        "book_id" integer NOT NULL REFERENCES "books_book" ("id") DEFERRABLE INITIALLY DEFERRED,
        "author_id" integer NOT NULL REFERENCES "books_author" ("id") DEFERRABLE INITIALLY DEFERRED,
        UNIQUE ("book_id", "author_id")
    )
    ;
    CREATE INDEX "books_book_publisher_id" ON "books_book" ("publisher_id");
    COMMIT;
    

    注意:

    自动生成的表名是app名称( books )和模型的小写名称 ( publisher , book , author )的组合。 关于Meta类

    我们前面已经提到,Django为每个表格自动添加加了一个 id 主键, 你可以重新设置它。

    按约定,Django添加 "_id" 后缀到外键字段名。 你猜对了,这个同样是可以自定义的。

    外键是用 REFERENCES 语句明确定义的。

    这些 CREATE TABLE 语句会根据你的数据库而作调整,这样象数据库特定的一些字段例如:(MySQL),auto_increment(PostgreSQL),serial(SQLite),都会自动生成。integer primary key 同样的,字段名称也是自动处理(例如单引号还好是双引号)。 例子中的输出是基于PostgreSQL语法的。

    sqlall 命令并没有在数据库中真正创建数据表,只是把SQL语句段打印出来,这样你可以看到Django究竟会做些什么。 如果你想这么做的话,你可以把那些SQL语句复制到你的数据库客户端执行,或者通过Unix管道直接进行操作(例如, python manager.py sqlall books | psql mydb)。不过,Django提供了一种更为简易的提交SQL语句至数据库的方法:syncdb命令

    python manage.py syncdb
    

    执行这个命令后,将看到类似以下的内容:

    Creating table books_publisher
    Creating table books_author
    Creating table books_book
    Installing index for books.Book model
    

    syncdb命令是同步你的模型到数据库的一个简单方法。 它会根据INSTALLED_APPS里设置的app来检查数据库, 如果表不存在,它就会创建它。 需要注意的是, syncdb 并不能将模型的修改或删除同步到数据库;如果你修改或删除了一个模型,并想把它提交到数据库,syncdb并不会做出任何处理。

    如果你再次运行python manage.py syncdb ,什么也没发生,因为你没有添加新的模型或者 添加新的app。因此,运行python manage.py syncdb总是安全的,因为它不会重复执行SQL语句。

    如果你有兴趣,花点时间用你的SQL客户端登录进数据库服务器看看刚才Django创建的数据表。 你可以手动启动命令行客户端(例如,执行PostgreSQL的psql命令),也可以执行 python manage.py dbshell,这个命令将依据DATABASE_SERVER 的里设置自动检测使用数据库命令行客户端。

    四、小结

    本节讲了模型的一些基本知识和命令, 开启Django定制的python shell:

    python manage.py shell
    

    在Django项目下创建新的APP:

    python manage.py startapp <app-name>
    

    检查models的语法:

    python manage.py validate
    

    根据models.py代码生成相应SQL代码:

    python manage.py sqlall <app-name>
    

    将上一步的SQL代码,提交到对应的数据库:

    python manage.py syncdb
    

    打开对应数据库的shell:

    python manage.py dbshell
    

    下一节,我们将知道通过Django来操作数据库,这都是基础。

    这里再次提醒大家,一定要去翻看Django对应版本(本课程使用1.4)官方文档,因为Django在不断的更新,老版本被开发者所诟病的设计,在1.4+的版本得到了很大的改善。

    Django 1.4 官方文档, 中国源,部分翻译

    作业

    请再新建一个app,创建课程、教师和学生三个模型用于选课,并处理好它们之间的关系。

     

  • 相关阅读:
    LeetCode 773. Sliding Puzzle
    oracle latch工作原理
    Oracle关于锁的几种类型和参数
    Java的反射机制
    JAVA多线程与并发学习总结
    Spring 概念详解
    Spring的AOP
    spring面试题 对DI , AOP概念的理解
    双11的架构
    Java线程的定义
  • 原文地址:https://www.cnblogs.com/mrchige/p/6399092.html
Copyright © 2020-2023  润新知