Python框架之Django学习笔记(十)

时间:2021-11-04 13:26:26

  又是一周周末,如约学习Django框架。在上一次,介绍了MVC开发模式以及Django自己的MVT开发模式,此次,就从数据处理层Model谈起。

  数据库配置

  首先,我们需要做些初始配置;我们需要告诉Django使用什么数据库以及如何连接数据库。假定你已经完成了数据库服务器的安装和激活,并且已经在其中创建了数据库(例如,用 CREATE DATABASE语句)。 如果你使用SQLite,不需要这步安装,因为SQLite使用文件系统上的独立文件来存储数据。和前面章节提到的 TEMPLATE_DIRS 一样,数据库配置也是在Django的配置文件settings.py 里。 打开这个文件并查找数据库配置:  

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

  原始配置如上所示,此为1.6.6版本的Django配置文件,恩,就是这样。如有不同也没关系。下面按照如下来配置数据库信息:  

 DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', #数据库种类
'NAME':'books', #数据名称
'USER':'root',
'PASSWORD':'',
'HOST':'127.0.0.1',
'PORT':'',
}
}

  配置保存之后,可以在命令行中进入工程目录下,如我的是“mysite”下,执行

 python manage.py shell

 进入命令行之后再进行测试。输入以下命令来进行测试: 

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

如果没有显示什么错误信息,那么恭喜你配置成功,否则,你就要查看错误信息来纠正错误,下面是一些常见的错误:

 Python框架之Django学习笔记(十)

第一个应用程序

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

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

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

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

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

  对于如何架构Django代码并没有快速成套的规则。 如果你只是建造一个简单的Web站点,那么可能你只需要一个app就可以了; 但如果是一个包含许多不相关的模块的复杂的网站,例如电子商务和社区之类的站点,那么你可能需要把这些模块划分成不同的app,以便以后复用。不错,你可以不用创建app,这一点应经被我们之前编写的视图函数的例子证明了 。 在那些例子中,我们只是简单的创建了一个称为views.py的文件,编写了一些函数并在URLconf中设置了各个函数的映射。 这些情况都不需要使用apps。但是,系统对app有一个约定: 如果你使用了Django的数据库层(模型),你 必须创建一个Django app。 模型必须存放在apps中。 因此,为了开始建造 我们的模型,我们必须创建一个新的app。

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

 python manage.py startapp books

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

 books/
__init__.py
admin.py
models.py
tests.py
views.py

  这个目录包含了这个app的模型和视图。使用你最喜欢的文本编辑器查看一下 models.py 和 views.py 文件的内容(博主大爱Sublime Text2)。 它们都是空的,除了 models.py 里有一个 import。这就是你Django app的基础。

第一个模型

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

  第一步是用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存取基本数据的所有代码。

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

模型安装

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

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

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
)

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

 INSTALLED_APPS = (
'mysite',
'books',
#'django.contrib.admin',
#'django.contrib.auth',
#'django.contrib.contenttypes',
#'django.contrib.sessions',
#'django.contrib.messages',
#'django.contrib.staticfiles',
)
   PS:就像我们在上一章设置TEMPLATE_DIRS所提到的逗号,同样在INSTALLED_APPS的末尾也需添加一个逗号,因为这是个单元素的元组。 另外,本书的作者喜欢在 每一个 tuple元素后面加一个逗号,不管它是不是 只有一个元素。 这是为了避免忘了加逗号,而且也没什么坏处。
  现在我们可以创建数据库表了。 首先,用下面的命令验证模型的有效性: 
 python manage.py validate

  validate 命令检查你的模型的语法和逻辑是否正确。 如果一切正常,你会看到 0 errors found 消息。如果出错,请检查你输入的模型代码。 错误输出会给出非常有用的错误信息来帮助你修正你的模型。一旦你觉得你的模型可能有问题,运行 python manage.py validate 。 它可以帮助你捕获一些常见的模型定义错误。模型确认没问题了,运行下面的命令来生成 CREATE TABLE 语句:

 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;

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

 python manage.py syncdb

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

基本数据访问

  一旦你创建了模型,Django自动为这些模型提供了高级的Python API。 运行 python manage.py shell 并输入下面的内容试试看:

 >>> from books.models import Publisher
>>> p1 = Publisher(name='Apress', address='2855 Telegraph Avenue',
... city='Berkeley', state_province='CA', country='U.S.A.',
... website='http://www.apress.com/')
>>> p1.save()
>>> p2 = Publisher(name="O'Reilly", address='10 Fawcett St.',
... city='Cambridge', state_province='MA', country='U.S.A.',
... website='http://www.oreilly.com/')
>>> p2.save()
>>> publisher_list = Publisher.objects.all()
>>> publisher_list
[<Publisher: Publisher object>, <Publisher: Publisher object>]

  这短短几行代码干了不少的事。 这里简单的说一下:

  • 首先,导入Publisher模型类, 通过这个类我们可以与包含 出版社 的数据表进行交互。
  • 接着,创建一个`` Publisher`` 类的实例并设置了字段" name, address" 等的值。
  • 调用该对象的 save() 方法,将对象保存到数据库中。 Django 会在后台执行一条 INSERT 语句。
  • 最后,使用"Publisher.objects" 属性从数据库取出出版商的信息,这个属性可以认为是包含出版商的记录集。 这个属性有许多方法, 这里先介绍调用"Publisher.objects.all()" 方法获取数据库中"Publisher" 类的所有对象。这个操作的幕后,Django执行了一条SQL "SELECT" 语句。

  这里有一个值得注意的地方,在这个例子可能并未清晰地展示。 当你使用Django modle API创建对象时Django并未将对象保存至数据库内,除非你调用"save()" 方法: 

 p1 = Publisher(...)
# At this point, p1 is not saved to the database yet!
p1.save()
# Now it i

  如果需要一步完成对象的创建与存储至数据库,就使用 "objects.create()" 方法。 下面的例子与之前的例子等价:

 >>> p1 = Publisher.objects.create(name='Apress',
... address='2855 Telegraph Avenue',
... city='Berkeley', state_province='CA', country='U.S.A.',
... website='http://www.apress.com/')
>>> p2 = Publisher.objects.create(name="O'Reilly",
... address='10 Fawcett St.', city='Cambridge',
... state_province='MA', country='U.S.A.',
... website='http://www.oreilly.com/')
>>> publisher_list = Publisher.objects.all()
>>> publisher_list

  当我们打印整个publisher列表时,我们没有得到想要的有用信息。

 [<Publisher: Publisher object>, <Publisher: Publisher object>]

  我们可以简单解决这个问题,只需要为Publisher 对象添加一个方法 __unicode__() 。 __unicode__() 方法告诉Python如何将对象以unicode的方式显示出来。 为以上三个模型添加__unicode__()方法后,就可以看到效果了:

 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() def __unicode__(self):
return self.name class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField() def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name) class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField() def __unicode__(self):
return self.title

  就象你看到的一样, __unicode__() 方法可以进行任何处理来返回对一个对象的字符串表示。 PublisherBook对象的__unicode__()方法简单地返回各自的名称和标题,Author对象的__unicode__()方法则稍微复杂一些,它将first_namelast_name字段值以空格连接后再返回。

  以上就是这次博文的主要内容,to be continued···

Python框架之Django学习笔记(十)的更多相关文章

  1. Python框架之Django学习笔记(十七)

    Django框架之表单(续二) 今天的这篇博客将是Django学习笔记博客的最后一篇,基本每周最少一篇的Django框架学习,坚持到今天也实属不易,当然了,这个框架的学习仅仅是Django框架的基础部 ...

  2. Python框架之Django学习笔记(十一)

    话说上次说到数据库的基本访问,而数据库我们主要进行的操作就是CRUD,也即是做计算处理时的增加(Create).读取(Retrieve)(重新得到数据).更新(Update)和删除(Delete),俗 ...

  3. Python框架之Django学习笔记(十二)

    Django站点管理 十一转眼结束,说好的充电没能顺利开展,反而悠闲的看了电视剧以及去影院看了新上映的<心花路放>.<亲爱的>以及<黄金时代>,说好的劳逸结合现在回 ...

  4. Python框架之Django学习笔记(十六)

    Django框架之表单(续) 今天简直无力吐槽了,去了香山,结果和网上看到的简直是天壤之别啊,说好的香山的枫树呢?说好的香山的红叶呢?说好的漫山遍野一片红呢?本以为在山上,一口气爬上去,沿路基本都是翠 ...

  5. Python框架之Django学习笔记(十五)

    表单 从Google的简朴的单个搜索框,到常见的Blog评论提交表单,再到复杂的自定义数据输入接口,HTML表单一直是交互性网站的支柱.本次内容将介绍如何用Django对用户通过表单提交的数据进行访问 ...

  6. Python框架之Django学习笔记(十四)

    Django站点管理(续·完) 本想昨天更新的,谁曾想昨天竟然是工作日!我就不吐槽昨天加班到十一点多了,需求增加无疑让我等蛋疼不已,忽而想起一首打油诗: 明月几时有,把酒问群友.不知这次版本,今晚能出 ...

  7. Python框架之Django学习笔记(六)

    模板 上篇博文学习了动态视图,但是,视图中返回文本的方式有点特别. 也就是说,HTML被直接硬编码在 Python 代码之中. def current_datetime(request): now = ...

  8. Python框架之Django学习笔记(九)

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

  9. Python框架之Django学习笔记(五)

    第一个Django网页小结 进来的请求转入/hello/. Django通过在ROOT_URLCONF配置来决定根URLconf. Django在URLconf中的所有URL模式中,查找第一个匹配/h ...

随机推荐

  1. 使用gulp工具生成svgsprites

    简介 SVG即可缩放矢量图形 (Scalable Vector Graphics)的简称, 是一种用来描述二维矢量图形的XML标记语言. SVG图形不依赖于分辨率, 因此图形不会因为放大而显示出明显的 ...

  2. Divide and conquer&colon;Telephone Lines&lpar;POJ 3662&rpar;

    电话线 题目大意:一堆电话线要你接,现在有N个接口,总线已经在1端,要你想办法接到N端去,电话公司发好心免费送你几段不用拉网线,剩下的费用等于剩余最长电话线的长度,要你求出最小的费用. 这一看又是一个 ...

  3. 《30天自制操作系统》05&lowbar;day&lowbar;学习笔记

    //bootpack.c 完整代码 #include <stdio.h> void io_hlt(void); void io_cli(void); void io_out8(int po ...

  4. Codeforces Round &num;361 &lpar;Div&period; 2&rpar;

    A 脑筋急转弯 // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream&g ...

  5. 最牛X的编码套路

    最近,我大量阅读了Steve Yegge的文章.其中有一篇叫"Practicing Programming"(练习编程),写成于2005年,读后令我惊讶不已: 与你所相信的恰恰相反 ...

  6. ZipDemo

    package swing.zip; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt. ...

  7. package。。

    如果在源代码内没有加上 package ... 是无法以下面的方式访问到主类的. D:\lab_>java timer.LambdaTest 加载时会返回 "错误: 找不到或无法加载主 ...

  8. idea添加JPA导出实体类

    https://blog.csdn.net/liu_yulong/article/details/72910588

  9. Laravel 门面实例教程 —— 创建自定义 Facades 类

    我们首先创建一个需要绑定到服务容器的Test类: <?php namespace App\Facades; class Test { public function doSomething() ...

  10. 使用 jQuery 调用 ASP&period;NET AJAX Page Method

    文章来源:http://chungle.iteye.com/blog/406054 说到轻量级的客户端通信,我注意到大多数人喜欢使用 ASP.NET AJAX Page Method 多于 ASMX ...