您的位置:首页 > 编程语言 > Go语言

Django学习之路4-Models

2017-03-28 00:00 459 查看
#Django Model,编写setting.py

每一个Django Model都继承自 django.db.models.Model

在Model当中每一个属性attribute都代表一个database field

通过Django Model API可以执行数据库的增删改查, 而不需要写一些数据库的查询语句

#设置数据库

Django项目建成后, 默认设置了使用SQLite数据库, 在my_blog/my_blog/setting.py中可以查看和修改数据库设置:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}

还可以设置其他数据库, 如MySQL, PostgreSQL, 现在为了简单, 使用默认数据库设置

#内容解析:

###INSTALLED_APPS

这里设置了自己创建的app,'article',每个新增的应用都要在这里创建

# Application definition
INSTALLED_APPS = (
'bootstrap_admin',    #新增
#默认包含的应用
'django.contrib.admin',    #网站管理框架
'django.contrib.auth',    #身份验证系统
'django.contrib.contenttypes',    #内容类型框架
'django.contrib.sessions',    #session 框架
'django.contrib.messages',    #消息框架
'django.contrib.staticfiles',    #静态文件管理框架

'article',
)

INSTALLED_APPS 设置

它保存了当前 Django 实例已激活的所有 Django 应用。每个应用可以被多个项目使用,而且你可以打包和分发给其他人在他们的项目中使用。

所有这些应用中每个应用至少使用一个数据库表,所以在使用它们之前我们需要创建数据库中的表。要做到这一点,请运行以下命令:

python manage.py syncdb

syncdb 命令参照 INSTALLED_APPS 设置,并在你的 settings.py 文件所配置的数据库中创建必要的数据库表。每创建一个数据库表你都会看到一条消息,接着你会看到一个提示询问你是否想要在身份验证系统内创建个超级用户。按提示输入后结束。

如果你感兴趣,可以在你的数据库命令行下输入:dt (PostgreSQL), SHOW TABLES; (MySQL), 或 .schema (SQLite) 来列出 Django 所创建的表。

极简主义者

就像我们上面所说的,一般情况下以上应用都默认包含在内,但不是每个人都需要它们。如果不需要某些或全部应用,在运行 syncdb 命令前可从 INSTALLED_APPS 内随意注释或删除相应的行。syncdb 命令只会为 INSTALLED_APPS 内的应用创建表。

###DATABASES

settings.py 是一个普通的 Python 模块,包含了代表 Django 设置的模块级变量。 更改 DATABASES 中 'default' 下的以下键的值,以匹配您的数据库连接设置。

# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } }

解析:

ENGINE – 从 'django.db.backends.postgresql_psycopg2', 'django.db.backends.mysql', 'django.db.backends.sqlite3', 'django.db.backends.oracle' 中选一个, 至于其他请查看 also available.

NAME – 你的数据库名。如果你使用 SQLite,该数据库将是你计算机上的一个文件;在这种情况下,NAME 将是一个完整的绝对路径,而且还包含该文件的名称。如果该文件不存在,它会在第一次同步数据库时自动创建(见下文)。

当指定路径时,总是使用正斜杠,即使是在 Windows 下(例如:C:/homes/user/mysite/sqlite3.db) 。

USER – 你的数据库用户名 ( SQLite 下不需要) 。

PASSWORD – 你的数据库密码 ( SQLite 下不需要) 。

H
7fe0
OST – 你的数据库主机地址。如果和你的数据库服务器是同一台物理机器,请将此处保留为空 (或者设置为 127.0.0.1) ( SQLite 下不需要) 。查看 HOST 了解详细信息。

如果你是新建数据库,我们建议只使用 SQLite ,将 ENGINE 改为 'django.db.backends.sqlite3' 并且将 NAME 设置为你想存放数据库的地方。 SQLite 是内置在 Python 中的,因此你不需要安装任何东西来支持你的数据库。

##Note
如果使用 PostgreSQL 或者 MySQL,确保你已经创建了一个数据库。还是通过你的数据库交互接口中的 “CREATE DATABASE database_name;” 命令做到这一点的。
如果你使用 SQLite ,你不需要事先创建任何东西 - 在需要的时候,将会自动创建数据库文件。
当你编辑 settings.py 时,将 TIME_ZONE 修改为你所在的时区。默认值是美国中央时区(芝加哥)。

#创建models

在 Django 中编写一个有数据库支持的 Web 应用的第一步就是定义你的模型 – 从本质上讲就是数据库设计及其附加的元数据。

哲理:
模型是有关你数据的唯一且明确的数据源。它包含了你所要存储的数据的基本字段和行为。 Django 遵循 DRY 原则 。目标是为了只在一个地方定义你的数据模型就可从中自动获取数据。

修改my_blog/article/models.py :

from django.db import models

# Create your models here.
class Article(models.Model) :
title = models.CharField(max_length = 100)  #博客题目
category = models.CharField(max_length = 50, blank = True)  #博客标签
date_time = models.DateTimeField(auto_now_add = True)  #博客日期
content = models.TextField(blank = True, null = True)  #博客文章正文

#python2使用__unicode__, python3使用__str__
def __str__(self) :
return self.title

class Meta:  #按时间下降排序
ordering = ['-date_time']

其中__str__(self) 函数Article对象要怎么表示自己, 一般系统默认使用<Article: Article object> 来表示对象, 通过这个函数可以告诉系统使用title字段来表示这个对象

CharField 用于存储字符串, max_length设置最大长度
TextField 用于存储大量文本
DateTimeField 用于存储时间, auto_now_add设置True表示自动设置对象增加时间


给模型添加 unicode() 方法

让我们编辑 polls 模型( 在 polls/models.py 文件中 ) 并且给 Poll 和 Choice 都添加一个 unicode() 方法来修正此错误:

class Poll(models.Model):
# ...
def unicode(self):
return self.question

class Choice(models.Model):
# ...
def unicode(self):
return self.choice_text
给你的模型添加 unicode() 方法是很重要的, 不仅是让你在命令行下有明确提示,而且在 Django 自动生成的管理界面中也会使用到对象的呈现。

为什么是 unicode() 而不是 str()?

如果你熟悉 Python,那么你可能会习惯在类中添加 str() 方法而不是 unicode() 方法。 We use 我们在这里使用 unicode() 是因为 Django 模型默认处理的是 Unicode 格式。当所有存储在数据库中的数据返回时都会转换为 Unicode 的格式。

Django 模型有个默认的 str() 方法 会去调用 unicode() 并将结果转换为 UTF-8 编码的字符串。这就意味着 unicode(p) 会返回一个 Unicode 字符串,而 str(p) 会返回一个以 UTF-8 编码的普通字符串。

如果这让你感觉困惑,那么你只要记住在模型中添加 unicode() 方法。 运气好的话,这些代码会正常运行。

在这简单的应用中,将创建模型:Article。 有title、category、date_time、content字段。

这些概念都由简单的 Python 类来表现

代码很简单。每个模型都由继承自 django.db.models.Model 子类的类来描述。 每个模型都有一些类变量,每一个类变量都代表了一个数据库字段。

每个字段由一个 Field 的实例来表现 – 比如 CharField 表示字符类型的字段和 DateTimeField 表示日期时间型的字段。这会告诉 Django 每个字段都保存了什么类型的数据。

** 每一个 Field 实例的名字就是字段的名字**(如: title 或者 content ),其格式属于亲和机器式的。在你的 Python 的代码中会使用这个值,而你的数据库会将这个值作为表的列名。

一些 Field 实例是需要参数的。 例如 CharField 需要你指定 ~django.db.models.CharField.max_length。这不仅适用于数据库结构,以后我们还会看到也用于数据验证中。

一个 Field 实例可以有不同的可选参数。

Django 支持常见数据库的所有关联:多对一( many-to-ones ),多对多( many-to-manys ) 和 一对一 ( one-to-ones )

激活模型

刚才那点模型代码提供给 Django 大量信息。有了这些 Django 就可以做:

为该应用创建对应的数据库架构 (CREATE TABLE statements) 。
为 Poll 和 Choice 对象创建 Python 访问数据库的 API 。
但首先,我们需要告诉我们的项目已经安装了 polls 应用。

哲理

Django 应用是“可插拔的”:你可以在多个项目使用一个应用,你还可以分发应用,因为它们没有被捆绑到一个给定的 Django 安装环境中。

再次编辑 settings.py 文件,在 INSTALLED_APPS 设置中加入 'polls' 字符。因此结果如下所示:
现在 Django 已经知道包含了 polls 应用。让我们运行如下命令:

现在你的 Django 项目会包含 polls 应用。接着运行下面的命令:

$ python manage.py makemigrations polls

你将会看到类似于下面这样的输出:

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

通过 migrations 命令,Django 会检测你对模型文件的修改,并且把修改的部分储存为一次 迁移。

迁移是 Django 对于模型定义(也就是你的数据库结构)的变化的储存形式 - 没那么玄乎,它们其实也只是一些你磁盘上的文件。

如果你想的话,你可以阅读一下你模型的迁移数据,它被储存在 polls/migrations/0001_initial.py 里。别担心,你不需要每次都阅读迁移文件,但是它们被设计成人类可读的形式,这是为了便于你手动修改它们。

Django 有一个自动执行数据库迁移并同步管理你的数据库结构的命令 - 这个命令是 migrate,我们马上就会接触它 - 但是首先,让我们看看迁移命令会执行哪些 SQL 语句。sqlmigrate 命令接收一个迁移的名称,然后返回给你对应的 SQL:

$ python manage.py sqlmigrate 0001

你将会看到类似下面这样的输出(我把输出重组成了人类可读的格式):

BEGIN;
CREATE TABLE "polls_choice" (
"id" serial NOT NULL PRIMARY KEY,
"choice_text" varchar(200) NOT NULL,
"votes" integer NOT NULL
);
CREATE TABLE "polls_question" (
"id" serial NOT NULL PRIMARY KEY,
"question_text" varchar(200) NOT NULL,
"pub_date" timestamp with time zone NOT NULL
);
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)和模型名的小写形式(question 和 choice)连接而来。(如果需要,你可以自定义此行为。)

主键(ID)会被自动创建。(当然,你也可以自定义。)

默认的,Django 会在外键字段名后追加字符串“_id”。(同样,这也可以自定义。)

外键关系由 FOREIGN KEY 生成。你不用关心 DEFERRABLE 部分,它只是告诉 PostgreSQL,请在事务全都执行完之后再创建外键关系。

生成的 SQL 语句是为你所用的数据库定制的,所以那些和数据库有关的字段类型,比如 auto_increment(MySQL)、serial(PostgreSQL)和 integer primary key autoincrement(SQLite),Django 会帮你自动处理。那些和引号相关的事情 - 例如,是使用单引号还是双引号 - 也一样会被自动处理。

sqlmigrate 命令并没有真正在你的数据库中的执行迁移 - 它只是把命令输出到屏幕上,让你看看 Django 认为需要执行哪些 SQL 语句。这在你想看看 Django 到底准备做什么,或者当你是数据库管理员,需要写脚本来批量处理数据库时会很有用。

如果你感兴趣,你也可以试试运行 python manage.py check ;这个命令帮助你检查项目中的问题,并且在检查过程中不会对数据库进行任何操作。

现在,再次运行 migrate 命令,在数据库里创建新定义的模型的数据表:

$ python manage.py migrate
Operations to perform:
Synchronize unmigrated apps: staticfiles, messages
Apply all migrations: admin, contenttypes, polls, auth, sessions
Synchronizing apps without migrations:
Creating tables...
Running deferred SQL...
Installing custom SQL...
Running migrations:
Rendering model states... DONE
Applying <migration name>... OK

migrate 命令选中所有还没有执行过的迁移(Django 通过在数据库中创建一个特殊的表 django_migrations 来跟踪执行过哪些迁移)并应用在数据库上 - 也就是将你对模型的更改同步到数据库结构上。

迁移是非常强大的功能,它能让你在开发过程中持续的改变数据库结构而不需要重新删除和创建表 - 它专注于使数据库平滑升级而不会丢失数据。

我们会在后面的教程中更加深入的学习这部分内容,现在,你只需要记住,改变模型需要这三步:

编辑 models.py 文件,改变模型。

运行 python manage.py makemigrations 为模型的改变生成迁移文件。

运行 python manage.py migrate 来应用数据库迁移。

数据库迁移被分解成生成和应用两个命令是为了让你能够在代码控制系统上提交迁移数据并使其能在多个应用里使用;这不仅仅会让开发更加简单,也给别的开发者和生产环境中的使用带来方便。

通过阅读文档 Django-admin documentation,你可以获得关于 manage.py 工具的更多信息。

#同步数据库

$ python manage.py migrate #命令行运行该命令

#然后执行下面的命令
$ python manage.py makemigrations
#得到如下提示
Migrations for 'article':
0001_initial.py:
- Create model Article

现在重新运行以下命令

$ python manage.py migrate
#出现如下提示表示操作成功
Operations to perform:
Apply all migrations: auth, sessions, admin, article, contenttypes
Running migrations:
Applying article.0001_initial... OK

migrate命令按照app顺序建立或者更新数据库, 将设置的数据库与 models.py同步

#Django Shell

现在我们进入Django中的交互式shell来进行数据库的增删改查等操作,就是进入 Python 的交互式 shell 中玩弄 Django 提供给你的 API

一旦你进入了 shell,就可通过 database API 来浏览数据:

$ python manage.py shell
Python 3.4.2 (v3.4.2:ab2c023a9432, Oct  5 2014, 20:42:22)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

这里进入Django的shell和python内置的shell是非常类似的

>>> from article.models import Article
>>> #create数据库增加操作
>>> Article.objects.create(title = 'Hello World', category = 'Python', content = '我们来做一个简单的数据库增加操作')
<Article: Article object>
>>> Article.objects.create(title = 'Django Blog学习', category = 'Python', content = 'Django简单博客教程')
<Article: Article object>

>>> #all和get的数据库查看操作
>>> Article.objects.all()  #查看全部对象, 返回一个列表, 无对象返回空list
[<Article: Article object>, <Article: Article object>]
>>> Article.objects.get(id = 1)  #返回符合条件的对象
<Article: Article object>

>>> #update数据库修改操作
>>> first = Article.objects.get(id = 1)  #获取id = 1的对象
>>> first.title
'Hello World'
>>> first.date_time
datetime.datetime(2014, 12, 26, 13, 56, 48, 727425, tzinfo=<UTC>)
>>> first.content
'我们来做一个简单的数据库增加操作'
>>> first.category
'Python'
>>> first.content = 'Hello World, How are you'
>>> first.content  #再次查看是否修改成功, 修改操作就是点语法
'Hello World, How are you'

>>> #delete数据库删除操作
>>> first.delete()
>>> Article.objects.all()  #此时可以看到只有一个对象了, 另一个对象已经被成功删除
[<Article: Article object>]

Blog.objects.all()  # 选择全部对象
Blog.objects.filter(caption='blogname')  # 使用 filter() 按博客题目过滤
Blog.objects.filter(caption='blogname', id="1") # 也可以多个条件
#上面是精确匹配 也可以包含性查询
Blog.objects.filter(caption__contains='blogname')

Blog.objects.get(caption='blogname') # 获取单个对象 如果查询没有返回结果也会抛出异常

#数据排序
Blog.objects.order_by("caption")
Blog.objects.order_by("-caption")  # 倒序

#如果需要以多个字段为标准进行排序(第二个字段会在第一个字段的值相同的情况下被使用到),使用多个参数就可以了
Blog.objects.order_by("caption", "id")

#连锁查询
Blog.objects.filter(caption__contains='blogname').order_by("-id")

#限制返回的数据
Blog.objects.filter(caption__contains='blogname')[0]
Blog.objects.filter(caption__contains='blogname')[0:3]  # 可以进行类似于列表的操作

当然还有更多的API, 可以查看官方文档
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: