• 第五章:数据库交换开发篇


    一、简要描述:

           Web 应用中,很多业务逻辑经常牵涉到与数据库的交互。 数据库驱动网站 在后台连接数据库服务器,从中取出一些数据,然后在 Web 页面用漂亮的格式展示这些数据。或者,站点也提供让访问者自行填充数据库的功能。

            只有使用

    1、简单数据查询

        


    from django.shortcuts import render_to_response
    import MySQLdb

    def book_list(request):
    db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost')
    cursor = db.cursor()
    cursor.execute('SELECT name FROM books ORDER BY name')
    names = [row[0] for row in cursor.fetchall()]
    db.close()
    return render_to_response('book_list.html', {'names': names})

      这种方法可以用,但是不是最理想的方法,在Web开放中是有很多数据操作类,如果每一个类都写数据连接,关闭那太繁琐了。

       我们希望不重复同样的代码:创建数据库连接、创建数据库游标、执行某个语句、然后关闭数据库。

       下介绍的内容中就可以解决这个问题,也是Django框架对Web开放的很好的支持。

    MTV 开发模式

     1、MVC:了解MTV之前我们还是先复习一下MVC吧。

      Django 紧紧地遵循这种 MVC 模式,可以称得上是一种 MVC 框架

    • M ,数据存取部分,由django数据库层处理,本章要讲述的内容。

    • V ,选择显示哪些数据要及怎样显示的部分,由视图和模板处理。

    • C ,根据用户输入委派视图的部分,由 Django 框架通过按照 URLconf 设置,对给定 URL 调用合适的 python 函数来自行处理。

     2、MTV:那到底什么是MTV呢?

        模型(Model)、模板(Template)和视图(Views),Django 也被称为 MTV 框架

    • M 代表模型(Model),即数据存取层。该层处理与数据相关的所有事务:如何存取、如何确认有效性、包含哪些行为以及数据之间的关系等。 

    • T 代表模板(Template),即表现层。该层处理与表现相关的决定:如何在页面或其他类型文档中进行显示。

    • V 代表视图(View),即业务逻辑层。该层包含存取模型及调取恰当模板的相关逻辑。你可以把它看作模型与模板之间的桥梁。

    数据库配置

      1、 缺省匹配

      打开项目Mysite在根目录下可以看到“ settings.py”文件,找到DATABASES 配置如下:

    DATABASES = {
    'default': {
    'ENGINE':'', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
    'NAME': '', # Or path to database file if using sqlite3.
    'USER': '', # Not used with sqlite3.
    'PASSWORD': '', # Not used with sqlite3.
    'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
    'PORT': '', # Set to empty string for default. Not used with sqlite3.
    }
    }

      代码描述:

     DATABASE_ENGINE 数据库引擎设置

     DATABASE_NAME 将数据库名称告知 Django 。如果使用 SQLite,请对数据库文件指定完整的文件系统路径。(例如 '/home/django/mydata.db' )。

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

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

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

      

      2、数据库引擎设置

          DATABASE_ENGINE 告诉Django使用哪个数据库引擎

                   数据库引擎设置
           设置                    数据库        适配器

          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/.

      ado_mssql           SQL Server     adodbapi 版本 2.0.1+, Microsoft SQL Server
      http://www.djangoproject.com/r/python-ado/.

      oracle                  Oracle             cx_Oracle ,
      http://www.djangoproject.com/r/python-oracle/.

     3、测试数据库配置

     启动了一个 Python 交互界面 : 运行 python manage.py shell 命令

     输入下面这些命令来测试你的数据库配置:

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

    如果没有显示什么错误信息,那么你的数据库配置是正确的.

    如果显示错误则配置数据库失败,检查错误代码,常见错误:

    错误信息:You havent set the DATABASE_ENGINE setting yet.

    解决方案:设置正确的 DATABASE_ENGINE 配置

    错误信息:Environment variable DJANGO_SETTINGS_MODULE is undefined.

    解决方案:运行命令行 python manage.py shell 而不是 python .

    错误信息:Error loading _____ module: No module named _____.

    解决方案:你没有安装相关的数据库适配器 (例如, psycopgMySQLdb ).

    错误信息:_____ isnt an available database backend.

    解决方案:设置正确的 DATABASE_ENGINE 配置也许是拼写错误?

    错误信息:database _____ does not exist

    解决方案:设置 DATABASE_NAME 配置到一个已有的数据库,或者使用 CREATE DATABASE 语句

                   创建数据库。

    错误信息:role _____ does not exist

    解决方案:修改 DATABASE_USER 配置到一个有效用户

    错误信息:could not connect to server

    解决方案:确认 DATABASE_HOSTDATABASE_PORT 设置是正确的,并确认服务器是在运行

                   的。

    第一个数据交换应用程序

     1、创建项目

      转到mysite项目目录,执行命令创建books目录

    python manage.py startapp books

     查看books文件目录中的文件:

    books/
    __init__.py
    models.py
    views.py

     2、定义数据模型

      打开 models.py 并输入下面的内容:

      

    # -*- coding:utf-8 -*-
    from django.db import models
    from django.contrib import admin

    class Publisher(models.Model):
    name = models.CharField(max_length=30,blank=True)
    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()
    def __unicode__(self):
    return self.name
    #默认排序设置
    #class Meta:
    # ordering = ["name"]

    #Admin 声明标志了该类有一个管理界面'''
    class Admin:
    pass

    class Author(models.Model):
    salutation=models.CharField(max_length=10)
    first_name=models.CharField(max_length=30)
    last_name=models.CharField(max_length=40)
    email=models.EmailField(max_length=30)
    #headshot = models.ImageField(upload_to='/tmp')
    def __unicode__(self):
    return '%s %s' % (self.first_name, self.last_name)
    #Admin 声明标志了该类有一个管理界面'''
    class Admin:
    pass

    class Book(models.Model):
    title=models.CharField(max_length=100)
    authors=models.ManyToManyField(Author)
    publisher=models.ForeignKey(Publisher)
    publication_date=models.DateField()
    num_page =models.IntegerField(blank=True,null=True)

    def __unicode__(self):
    return 'Book name :%s' % self.title

    模型安装

    再次编辑 settings.py 文件, 找到 INSTALLED_APPS 设置 ,INSTALLED_APPS 告诉 Django 项目哪些 app 处于激活状态,

    缺省情况下如下所示:

    INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    )

    INSTALLED_APPS 设置中四个设置前面加#临时注释起来,

    改缺省的 MIDDLEWARE_CLASSESTEMPLATE_CONTEXT_PROCESSORS 设置,都注释起来。然后添加 'mysite.books'INSTALLED_APPS 列表,现在看起来是这样:

    MIDDLEWARE_CLASSES = (
    # 'django.middleware.common.CommonMiddleware',
    #
    'django.contrib.sessions.middleware.SessionMiddleware',
    #
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    #
    'django.middleware.doc.XViewMiddleware',
    )

    TEMPLATE_CONTEXT_PROCESSORS = ()
    #...

    INSTALLED_APPS = (
    #'django.contrib.auth',
    #'django.contrib.contenttypes',
    #'django.contrib.sessions',
    #'django.contrib.sites',
    'mysite.books',
    )

    校验模型的有效性:

    python manage.py validate

    0 errors found 消息:表示一切正常

    否则就是错误,检查数据模型是否正确。

    生成SQL语句:

    python manage.py sqlall books

     运行命令的结果是这样的:

    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_book" (
    "id" serial NOT NULL PRIMARY KEY,
    "title" varchar(100) NOT NULL,
    "publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id"),
    "publication_date" date NOT NULL
    );
    CREATE TABLE "books_author" (
    "id" serial NOT NULL PRIMARY KEY,
    "salutation" varchar(10) NOT NULL,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(40) NOT NULL,
    "email" varchar(75) NOT NULL,
    "headshot" varchar(100) NOT NULL
    );
    CREATE TABLE "books_book_authors" (
    "id" serial NOT NULL PRIMARY KEY,
    "book_id" integer NOT NULL REFERENCES "books_book" ("id"),
    "author_id" integer NOT NULL REFERENCES "books_author" ("id"),
    UNIQUE ("book_id", "author_id")
    );
    CREATE INDEX books_book_publisher_id ON "books_book" ("publisher_id");
    COMMIT;


    代码描述:

       A、自动生成的表名是app名称( books )和模型的小写名称( publisher , book , author )的组合
       B、Django会站点添加一个ID主键,是可以修改的。

       C 、按约定规则,Django添加的"_id"后缀到外键字段名。

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

        E、这些 CREATE TABLE 语句会根据你的数据库而作调整,这样象数据库特定的一些字段例如: auto_increment (MySQL), serial (PostgreSQL), integer primary key (SQLite) 可以自动处理。

    同步数据库:

    python manage.py syncdb

    你将会看到这样的内容:

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

    重启服务器:

     重启Web服务器

    python manage.py runserver

    数据访问类

      python manage.py shell 进入

     1、获取所以数据

    >>> from books.models import Publisher
    >>> publisher_list = Publisher.objects.all()
    >>> publisher_list
    [<Publisher: lhj-588>, <Publisher: loker>]

    2、插入数据

    >>> from books.models import Publisher
    >>>p = Publisher(name='Apress',
    ... address='2855 Telegraph Ave.',
    ... city='Berkeley',
    ... state_province='CA',
    ... country='U.S.A.',
    ... website='http://www.apress.com/')
    >>> p.save()

    转换成SQL:

    INSERT INTO book_publisher
    (name, address, city, state_province, country, website)
    VALUES
    ('Apress', '2855 Telegraph Ave.', 'Berkeley', 'CA',
    'U.S.A.', 'http://www.apress.com/');

    3、修改数据

    >>> from books.models import Publisher
    >>>p = Publisher(name='Apress'
    ,... address='2855 Telegraph Ave.'
    ,... city='Berkeley'
    ,... state_province='CA'
    ,... country='U.S.A.'
    ,... website='http://www.apress.com/')
    >>> p.save()
    >>> p.id
    3
    >>> p.name ='apress Publishing'
    >>> p.save()


     后面执行的 save() 相当于下面的SQL语句:

    UPDATE book_publisher SET
    name = 'Apress Publishing',
    address = '2855 Telegraph Ave.',
    city = 'Berkeley',
    state_province = 'CA',
    country = 'U.S.A.',
    website = 'http://www.apress.com'
    WHERE id = 52;

    4、过滤数据  filter()

    >>> from books.models import Publisher
    >>>Publisher.objects.filter(country="U.S.A.", state_province="CA")
    [<Publisher: Apress Publishing>]

    相当于SQL语句:

    SELECT
    id, name, address, city, state_province, country, website
    FROM book_publisher
    WHERE country = 'U.S.A.' AND state_province = 'CA';

    5、获取单个对象

    >>> from books.models import Publisher
    >>>Publisher.objects.get(name="Apress Publishing")
    [<Publisher: Apress Publishing>]

    如果查询出多个对象,则会导致抛出异常。

    6、数据排序 order_by

    >>> from books.models import Publisher
    >>>Publisher.objects.order_by("name")
    [<Publisher: Apress Publishing>, <Publisher: Addison-Wesley>, <Publisher: O'Reilly>]

    相当于SQL:

    SELECT
    id, name, address, city, state_province, country, website
    FROM book_publisher
    ORDER BY name;

    可以指定逆向排序

    Publisher.objects.order_by("-name")
     
    7、限制返回的数据
     
    >>>from books.models import Publisher
    >>>Publisher.objects.all()[0]
    <Publisher: Addison-Wesley>
    >>>Publisher.objects.all()[0:2]
    [<Publisher: Addison-Wesley>, <Publisher: Apress Publishing>, <Publisher: Addison-Wesley>]
    
    
    8、删除对象.delete()
    >>>from books.models import Publisher
    >>>p = Publisher.objects.get(name="Addison-Wesley")
    >>> p.delete()
    >>> Publisher.objects.all()
    [<Publisher: Apress Publishing>, <Publisher: O'Reilly>]
    >>>publishers.delete()
    >>> Publisher.objects.all()
    []

    修改数据库表结构

    你需要查看 manage.py sqlall 的执行结果 

      同用步骤:

      A、修改数据模型

      B、同步数据库:执行python manage.py syncdb

      C、重启服务器:执行python manage.py runserver

    先修改在开发环境而不是发布服务器上修改

    1、添加字段

    在开发环境中执行下面的步骤:

    1. 把这个字段添加到你的模型中.

    1. 运行 manage.py sqlall [yourapp] 会看到模型的新的 CREATE TABLE 语句。注意新的字段的列定义。

    1. 启动您的数据库交互shell(也就是 psqlmysql , 或者您也可以使用 manage.py dbshell )。 执行一个 ALTER TABLE 语句,添加您的新列

        4. (可选)用 manage.py shell 动ython交互式shell,并通过引入模型并选择表验证新的字段已被正确添加(比如, MyModel.objects.all()[:5] )。

    然后在发布服务器上执行下面的步骤: 

    1. 启动你的数据库的交互式命令行;

    1. 执行 ALTER TABLE 语句,也就是在开发环境中第3步执行的语句;

    1. 添加字段到你的模型中。如果你在开发时使用了版本控制系统并checkin了你的修改,现在可以更新代码到发布服务器上了(例如,使用Subverison的话就是 svn update )。

    1. 重启Web服务器以使代码修改生效

    2、删除字段

    从模型里删除一个字段可要比增加它简单多了。删除一个字段仅需要做如下操作:

    从你的模型里删除这个字段,并重启Web服务器。

    使用如下面所示的命令,从你的数据库中删掉该列:

    3、删除 Many-to-Many 字段

    因为many-to-many字段同普通字段有些不同,它的删除过程也不一样:

    删除掉你的模型里的 ManyToManyField ,并且重启Web服务器。

    使用如下面所示的命令,删除掉你数据库里的many-to-many表:

    DROP TABLE books_books_publishers;

    4、删除模型

    完全删除一个模型就像删除一个字段一样简单。删除模型仅需要做如下步骤:

    将此模型从你的 models.py 文件里删除,并且重启Web服务器。

    使用如下的命令,将此表从你的数据库中删除:

    DROP TABLE books_book;


     

  • 相关阅读:
    Exchange这东东…
    下午解决了一个问题
    PDC每日视频
    Delphi.net的IDE和C#Builder是相同的
    开始把准备把Exchange的一些基本操作和设置与SharePoint结合起来
    这两天忙得焦头烂额
    一个在.net下进行用户模拟的类
    SharePoint的相关链接
    今天才知有一个CollectionBase类,惭愧
    【博客堂杯征文】从服务员到程序员
  • 原文地址:https://www.cnblogs.com/lhj588/p/2231825.html
Copyright © 2020-2023  润新知