第1章 介绍Django

  1. 本质上来说,Django只不过是用python编写的一组类库。用Django开发站点就是使用这些类库编写python代码。学习Django的关键就是学习如何进行python编程并理解Django类库的运作方式。
  2. pip是一个以Python写成的软件包管理系统,他可以安装和管理python软件包。pip支持从PyPI上安装,PyPI上有所有的python包列表:https://pypi.python.org/pypi?%3Aaction=index。https://pypi.python.org/pypi?%3Aaction=browse。我安装Django,按照https://www.djangoproject.com/download/的指导,直接用pip:pip install Django==1.7.7
  3. 不过,当你想开发一个数据库驱动的web站点时,你应当需要配置一个数据库服务器。Django支持四种数据库:PostgreSQL (http://www.postgresql.org),SQLite 3 (http://www.sqlite.org),MySQL (http://www.mysql.com/),Oracle (http://www.oracle.com/)。
  4. 如果你只是玩一下,不想安装数据库服务,那么可以考虑使用SQLite。如果你使用python2.5或更高版本的话,SQLite是唯一一个被支持的且不需要以上安装步骤的数据库。它仅对你的文件系统中的单一文件读写数据,并且python 2.5和以后版本内建了对它的支持。
  5. 在Django中使用MySQL,django要求MySQL4.0或更高的版本。3.X版本不支持嵌套子查询和一些其它相当标准的SQL语句。如果你正在使用Linux,检查下你系统的包管理器是否提供了叫做python-mysql, python-mysqldb, mysql-python或者相似的包。用pip安装:pip install MySQL-python,我已经装过MySQL了~我的Django是默认安装在这儿的:/usr/local/lib/python2.7/dist-packages。我的MySQL是默认装在这儿的:/usr/lib/python2.7/dist-packages。看来Linux对于不常用的python模块还是会小心一些的。

第3章 视图和URL配置

  1. 使用Django,你会用不同的方法来说明这两件事:页面的内容是靠view function(视图函数)来产生,URL定义在URLconf中。
  2. 每个视图函数至少要有一个参数,通常被叫做request。这是一个触发这个视图、包含当前Web请求信息的对象,是类django.http.HttpRequest的一个实例。一个视图就是Python的一个函数。这个函数第一个参数的类型是HttpRequest;它返回一个HttpResponse实例。为了使一个Python的函数成为一个Django可识别的视图,它必须满足这两个条件。
  3. URLconf(即urls.py)就像是Django所支持网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表。例如,当用户访问/foo/时,调用视图函数foo_view(),这个视图函数存在于Python模块文件view.py中。
  4. 我们为urlpatterns加上一行:(‘^hello/$’, hello),这行被称作URLpattern,它是一个python的元组。元组中第一个元素是模式匹配字符串(正则表达式);第二个元素是那个模式将使用的视图函数。
  5. 模式包含了一个尖号(^)和一个美元符号()
    的模式’^hello/’,那么任何以/hello/开头的URL将会匹配,例如:/hello/foo和/hello/bar,而不仅仅是/hello/。类似地,如果我们忽略了尖号(^),即’hello/hello/URL/foo/bar/hello/使hello/
    结尾,那么任何包含hello/的URL将会匹配,如:/foo/hello/bar。因此,我们使用这两个符号以确保只有/hello/匹配,不多也不少。
  6. Django在检查URL模式前,移除每一个申请的URL开头的斜杠(/)。默认地,任何不匹配或尾部没有斜杠(/)的申请URL,将被重定向至尾部包含斜杠的相同字眼的URL。
  7. 另外需要注意的是,我们把hello视图函数作为一个对象传递,而不是调用它。这是python(及其它动态语言的)一个重要特性:函数是一级对象(first-class objects),也就是说你可以像传递其它变量一样传递它们。很酷吧?
  8. Django的开发服务器(python manage.py runserver)可以让它一直运行,开发服务器会自动检测代码改动并自动重新载入,所以不需要手工重启。
  9. 这个页面比原始的404错误信息更加实用。它同时精确的告诉你Django调用哪个URLconf及其包含的每个模式。这样,你应该能了解到为什么这个请求会抛出404错误。当然,这些敏感的信息应该只呈现给你 - 开发者。如果是部署到了因特网上的站点就不应该暴露这些信息。出于这个考虑,这个”Page not found”页面只会在 调试模式(debug mode)下显示。我们将在以后说明怎么关闭调试模式。
  10. 当访问URL /hello/时,Django根据ROOT_URLCONF(在settings.py里)的设置装载URLconf。然后按顺序逐个匹配URLconf里的URLpatterns,直到找到一个匹配的。当找到这个匹配的URLpattern就调用相关联的view函数,并把HttpRequest对象作为第一个参数。视图函数返回一个HttpResponse,Django转换HttpResponse为一个适合的HTTP response,以Web page显示出来。
  11. 字符串后面的%表示用它后面的变量now的值来代替%s。记住在urls.py里每一个视图函数都要import!
  12. Django时区,默认时区为America/Chicago。修改在settings.py。在Django的应用程序中,URL的定义和视图函数之间是松耦合的,换句话说,决定URL返回哪个视图函数和实现这个视图函数是在两个不同的地方。这使得开发人员可以修改一块而不会影响另一块。
  13. 如果你有其他Web平台的开发经验(如PHP或Java),你可能会想:嘿!让我们用查询字符串参数吧!就像/time/plus?hours=3里面的小时应该在查询字符串中被参数hours指定。你可以在Django里也这样做,但是Django的一个核心理念就是URL必须看起来漂亮。URL /time/plus/3/更加清晰,更简单,也更有可读性,因为它是纯文本,没有查询字符串那么复杂。漂亮的URL就像是高质量的Web应用的一个标志。
  14. 正则表达式字符串的开头字母”r”。它告诉Python这是个原始字符串,不需要处理里面的反斜杠(转义字符)。由于反斜杠在Python代码和正则表达式中有冲突,因此建议你在Python定义正则表达式时都使用原始字符串。从现在开始,本文所有URL模式都用原始字符串。
  15. 现在我们已经设计了一个带通配符的URL,我们需要一个方法把它传递到视图函数里去,这样我们只用一个视图函数就可以处理所有的时间段了。我们使用圆括号把参数在URL模式里标识出来:url(r’^time/plus/(\d{1,2})/$’, hours_ahead), 如果你熟悉正则表达式,那么你应该已经了解,正则表达式也是用圆括号来从文本里提取数据的。请注意:捕获值永远都是字符串(string)类型,而不会是整数类型。(从技术上来说,捕获值总是Unicode objects,而不是简单的Python字节串,但目前不需要担心这些差别。)
  16. 不知道你是不是哪种使用小心放置的print语句来帮助调试的程序员?你其实可以用Django出错页来做这些,而不用print语句。在你视图的任何位置,临时插入一个assert False来触发出错页。然后你就可以看到局部变量和程序语句了。太赞了!!!!

第4章 模版

  1. 前面的例子里,HTML被直接硬编码在Python代码之中。为什么不好?
    No.1:对页面设计进行的任何改变都必须对Python代码进行相应的修改。站点设计的修改往往比底层Python代码的修改要频繁得多,因此如果可以在不进行Python代码修改的情况下变更设计,那将会方便得多。
    No.2:Python代码编写和HTML设计是两项不同的工作,大多数专业的网站开发环境都将他们分配给不同的人员(甚至不同部门)来完成。设计者和HTML/CSS的编码人员不应该被要求去编辑Python的代码来完成他们的工作。
    No.3:程序员编写Python代码和设计人员制作模板两项工作同时进行的效率是最高的,远胜于让一个人等待另一个人完成对某个既包含Python又包含HTML的文件的编辑工作。
    基于这些原因,将页面的设计和Python的代码分离开会更干净简洁更容易维护。我们可以用Django的模板系统(Template System)来实现这种模式。
  2. 模板是一个文本,用于分离文档的表现形式和内容。模板定义了占位符以及各种用于规范文档该如何显示的各部分基本逻辑(模板标签)。模板通常用于产生HTML,但是Django的模板也能产生任何基于文本格式的文档。
  3. 用两个大括号括起来的文字(例如{{ person_name }})称为变量variable,这意味着在此处插入指定变量的值。
  4. 被大括号和百分号包围的文本(例如 {% if ordered_warranty %})是模板标签template tag,标签tag定义比较明确,即:仅通知模板系统完成某些工作的标签。标签就相当于在文本里嵌入程序语言。
  5. 关于filter过滤器的例子,它是一种最便捷的转换变量输出格式的方式。如这个例子中的{{ship_date | date:”F j, Y”}},将变量ship_date传递给date过滤器,同时指定参数”F j, Y”。date过滤器根据参数进行格式输出。过滤器是用管道符(|)来调用的,具体可以参见Unix管道符。

如何使用模板系统

  1. 在Python代码中使用Django模板的最基本方式:
    No.1:可以用原始的模板代码字符串创建一个Template对象,Django同样支持用指定模板文件路径的方式来创建Template对象。
    No.2:调用模板对象的render方法,并且传入一套变量context。它将返回一个基于模板的展现字符串,模板中的变量和标签会被context值替换。
  2. 在:
>>>from django import template
>>>t = template.Template('My name is {{ name }}.')

时会出错:

django.core.exceptions.ImproperlyConfigured: Requested setting TEMPLATE_DEBUG, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

这个时候,我们只要输入:

>>>from django.conf import settings
>>>settings.configure()

之后

>>> t = template.Template('My name is {{ name }}.')

就对了。接着给这个template对象传入context:

c = template.Context({'name': 'Adrian'})

让Template调用Context只要:

print t.render(c)

只不过这样,每次开启一个python shell都要重新call settings.configure。第二个方法是输入命令

python manage.py shell

这个打开的shell与python shell界面不太一样,应该是ipython。这两个命令都是启动交互解释器,但是manage.py shell命令有一个重要的不同:在启动解释器之前,它告诉Django使用哪个设置文件。使用python manage.py shell就是告诉解释器去使用mysite里的settings.py。但是我在我的settings.py并没有找到DJANGO_SETTINGS_MODULE这个环境变量。。。但是有这一行:

TEMPLATE_DEBUG = True

随着你越来越熟悉Django,你可能会偏向于废弃使用”manage.py shell”,而是在你的配置文件.bash_profile中手动添加DJANGO_SETTINGS_MODULE这个环境变量。

当你创建一个Template对象,模板系统在内部编译这个模板到内部格式,并做优化,做好渲染的准备。如果你的模板语法有错误,那么在调用Template()时就会抛出TemplateSyntaxError异常。如:无效的tags,标签的参数无效,无效的过滤器,过滤器的参数无效,无效的模板语法,未封闭的块标签。

模板渲染

  1. 一旦你创建一个Template对象,你可以用context来传递数据给它。一个context是一系列变量和它们值的集合。Context的构造函数带有一个可选的参数:一个字典映射变量和它们的值。调用Template对象的render()方法并传递context来填充模板。t.render(c)返回的值是一个Unicode对象,不是普通的Python字符串。你可以通过字符串前面的u来区分。你只需要知道Django对Unicode的支持,将让你的应用程序轻松地处理各式各样的字符集,而不仅仅是基本的A-Z英文字符。
  2. 我们把模板原始文本保存到变量raw_template。注意到我们使用了三个引号来标识这些文本,因为这样可以包含多行。
  3. 如果你是Python初学者,你可能在想为什么输出里有回车换行的字符(’\n’)而不是显示回车换行?因为这是Python交互解释器的缘故:调用t.render(c)返回字符串,解释器缺省显示这些字符串的真实内容呈现,而不是打印这个变量的值。要显示换行而不是’\n’,使用print语句:print t.render(c)。
  4. Django模板解析非常快捷。大部分的解析工作都是在后台通过对简短正则表达式一次性调用来完成。这和基于XML的模板引擎形成鲜明对比,那些引擎承担了XML解析器的开销,且往往比Django模板渲染引擎要慢上几个数量级。
  5. 点语法也可以用来引用对象的方法,例如每个Python字符串都有upper()和isdigit()方法,你在模板中可以使用同样的句点语法来调用它们:
t = Template('{{var}} -- {{var.upper}} -- {{var.isdigit}}')

注意这里调用方法时并没有使用圆括号,而且也无法给该方法传递参数;你只能调用不需参数的方法。最后,句点也可用于访问列表索引。不允许使用负数列表索引。像{{ items.-1 }}这样的模板变量将会引起”TemplateSyntaxError”。
10. 句点查找规则可概括为:当模板系统在变量名中遇到点时,按照一下顺序尝试进行查找:
No.1: 字典类型查找,比如foo[“bar”]
No.2: 属性查找,比如foo.bar
No.3: 方法调用,比如foo.bar()
No.4: 列表类型索引查找,比如foo[bar]
系统使用找到的第一个有效类型,这是一种短路逻辑。
11. 在Python和Django模板系统中,以下这些对象相当于布尔值的False:空列表[],空元组(),空字典{},空字符串”,零值0,特殊对象None,对象False。
12. 并没有{% elif %}标签,请在{% else %}中使用嵌套的“{% if %}”。一定要用{% endif %}关闭每一个{% if %}标签。给标签增加一个reversed使得该列表被反向迭代:{% for athlete in athlete_list reversed %} … {% endfor %}。在执行for之前,先用if来检测一下列表是否为空。这可以通过{% empty %}标签来实现。{% ifequal user currentuser %}。只有模板变量、字符串、整数和小数可以作为{% ifequal %}标签的参数,其他任何类型,例如Python的字典类型、列表类型、布尔类型,不能用在{% ifequal %}中。注释使用{# #},用这种语法的注释不能跨越多行,这个限制是为了提高模板解析的性能。实现多行注释可以用{% comment %}和{% endcomment %}。
13. 有些过滤器有参数。过滤器的参数跟随冒号之后并且总是以双引号包含。例如:{{ bio | truncatewords:”30” }},这个将显示变量bio的前30个词。
14. 几个最重要的过滤器:
No.1: addslashes: 添加反斜杠到任何反斜杠、单引号或者双引号前面。这在处理包含JavaScript的文本时是非常有用的。
No.2: date: 按指定的格式字符串参数格式化date或者datetime对象,例如:

{{ pub_date|date:"F j, Y" }}

No.3: length: 返回变量的长度。
15. 相对于其他的网络应用的组件,模板的语法很具主观性,因此可供程序员的选择方案也很广泛。事实上,Python有成十上百的开放源码的模板语言实现。每个实现都是因为开发者认为现存的模板语言不够用。事实上,对一个Python开发者来说,写一个自己的模板语言就像是某种”成人礼”一样!如果你还没有完成一个自己的模板语言,好好考虑写一个,这是一个非常有趣的锻炼。
16. 业务逻辑应该和表现逻辑相对分开。我们将模板系统视为控制表现及表现相关逻辑的工具,模板系统不应提供超出此基本目标的功能。出于这个原因,在Django模板中是不可能直接调用Python代码的。所有的编辑工作基本上都被局限于模板标签的能力范围。
17. 语法不应受到HTML/XML的束缚。尽管Django模板系统主要用于生成HTML,它还是被有意地设计为可生成非HTML格式,如纯文本。一些其它的模板语言是基于XML的,将所有的模板逻辑置于XML标签与属性之中,而Django有意地避开了这种限制。强制要求使用有效XML编写模板将会引发大量的人为错误和难以理解的错误信息,而且使用XML引擎解析模板也会导致令人无法容忍的模板处理开销。
18. 假定设计师精通HTML编码!!!模板系统的设计意图并不是为了让模板一定能够很好地显示在Dreamweaver这样的所见即所得编辑器中。这种限制过于苛刻,而且会使得语法不能像目前这样的完美。Django要求模板创作人员对直接编辑HTML非常熟悉。HTML编码很容易吧,精通是什么意思?
19. 假定设计师不是Python程序员。模板系统开发人员认为:模板通常由设计师而非程序员来编写,因此不应被假定拥有Python开发知识。
20. 第一次装载Template!!!首先在/home/sen/djcode/mysite/下新建templates文件夹,并将该路径添加到settings.py中:

TEMPLATE_DIRS = ('/home/sen/djcode/mysite/templates', )

然后在/home/sen/djcode/mysite/templates中新建了一个current_datetime.html文件作为模板:

<html><body>It is now {{ current_date }}.</body></html>

最后修改views.py:

from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
import datetimedef current_time(request):now = datetime.datetime.now()t = get_template('current_datetime.html')html = t.render(Context({'current_date': now}))return HttpResponse(html)

现在在浏览器输入192.168.1.142:8000/time/时就可以了。
21. 该get_template()函数以模板名称为参数,在文件系统中找出模块的位置,打开文件并返回一个编译好的Template对象。
22. 使用render_to_response()对20的代码优化,render_to_response包含了模板加载、上下文创建、模板解析和HttpResponse创建工作!

from django.shortcuts import render_to_response
import datetimedef current_time(request):now = datetime.datetime.now()return render_to_response('current_datetime.html', {'current_date': now})

render_to_response()的第一个参数必须是要使用的模板名称。如果要给定第二个参数,那么该参数必须是为该模板创建Context时所使用的字典。如果不提供第二个参数,render_to_response()使用一个空字典。
23. 我总觉得这里还是没有彻底将模板和Python解耦合,因为’current_date’仍然是模板内部的变量名字!!!!!!
24. {% include %}:该标签允许在(模板中)包含其它的模板的内容。标签的参数是所要包含的模板名称,可以是一个变量,也可以是用单/双引号硬编码的字符串。每当在多个模板中出现相同的代码时,就应该考虑是否要使用{% include %}来减少重复。

模板继承

  1. 模板继承:本质上来说,模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载。
  2. 很明显,我们刚才重复了大量的HTML代码。想象一下,如果有一个更典型的网站,它有导航条、样式表,可能还有一些JavaScript代码,事情必将以向每个模板填充各种冗余的HTML而告终。
    No.1: 解决这个问题的服务器端include方案是找出两个模板中的共同部分。将其保存为不同的模板片段,然后在每个模板中进行include。
    No.2: Django的模板继承系统解决了这些问题。你可以将其视为服务器端include的逆向思维版本。你可以对那些不同的代码段进行定义,而不是共同代码段。
  3. 第一步是定义基础模板,该框架之后将由子模板所继承:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head><title>{% block title %}{% endblock %}</title>
</head>
<body><h1>My helpful timestamp site</h1>{% block content %}{% endblock %}{% block footer %}<hr><p>Thanks for visiting my site.</p>{% endblock %}
</body>
</html>

这个叫做base.html的模板定义了一个简单的HTML框架文档,我们将在本站点的所有页面中使用。子模板的作用就是重载、添加或保留那些块的内容。

第二步:现在我们已经有了一个基本模板,我们可以修改current_datetime.html模板来使用它:

{% extends "base.html" %}{% block title %}The current time{% endblock %}{% block content %}
<p>It is now {{ current_date }}.</p>
{% endblock %}

多数情况下,{% extends %}的参数应该是字符串,但是如果直到运行时方能确定父模板名,这个参数也可以是个变量。这使得你能够实现一些很酷的动态功能。
28. 时下大多数网站都是数据库驱动的:网站的内容都是存储在关系型数据库中。这使得数据和逻辑能够彻底地分开(视图和模板也以同样方式对逻辑和显示进行了分隔)。

第5章 模型

  1. 在当代Web应用中,主观逻辑经常牵涉到与数据库的交互。数据库驱动网站在后台连接数据库服务器,从中取出一些数据,然后Web页面用漂亮的格式展示这些数据。这个网站也可能会向访问者提供修改数据库数据的方法。许多复杂的网站都提供了以上两个功能的某种结合。例如Amazon.com就是一个数据库驱动站点的良好范例。本质上,每个产品页面都是数据库中数据以HTML格式进行的展现,而当你发表客户评论时,该评论被插入评论数据库中。
  2. 把数据存取逻辑、业务逻辑和表现逻辑组合在一起的概念有时被称为软件架构的Model-View-Controller(MVC)模式。在这个模式中,Model代表数据存取层,View代表的是系统中选择显示什么和怎么显示的部分,Controller指的是系统中根据用户输入并视需要访问模型,以决定使用哪个视图的那部分。
  3. Django紧紧地遵循这种MVC模式,可以称得上是一种MVC框架。Django中M、V、C各自的含义:
    M: 数据存取部分,由django数据库层处理。
    V: 选择显示哪些数据要显示以及怎样显示的部分,由视图和模板处理。
    C: 根据用户输入委派视图的部分,由Django框架根据URLconf设置,对给定URL调用适当的Python函数。
    由于C由框架自行处理,而Django里更关注的是模型(Model)、模板(Template)和视图(Views),Django也被称为MTV框架。在MTV开发模式中:
    M: 数据存取层,该层处理与数据相关的所有事务:如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
    T: 表现层,该层处理与表现相关的决定:如何在页面或其他类型文档中进行显示。
    V: 业务逻辑层,该层包含存取模型及调取恰当模板的相关逻辑。你可以把它看做模型与模板之间的桥梁。
  4. 我先安装mysql
sudo apt-get install mysql-server

设置root密码:klm****。
然后进入mysql的shell:

mysql -u root -p

显示当前数据库中的数据库:

SHOW DATABASES;

mysql指令一定要以分号结束。
新建数据库:

CREATE DATABASE django_db

好像还需要相应的Python适配器,我
pip search MySQL-python
显示

MySQL-python    - Python interface to MySQLINSTALLED: 1.2.3LATEST: 1.2.5
cozydb    - cozydb is a cozy MySQL-python wrapper
MySQL-python-embedded    - Python interface to MySQL
MySQL-python-glb    - Python interface to MySQL
mysql    - Virtual package for MySQL-python

有点不太理解这个mysql到底能不能替代上面安装的mysql-server。我已经装了MySQL-python。
接着我修改settings.py里的DATABASES设置:

'ENGINE': 'django.db.backends.mysql',
'NAME': 'django_db',
'USER': 'root',
'PASSWORD': 'klm****',

现在我在ipython里试试连接数据库是否成功了:

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

第一个应用程序

  1. project和app之间的区别:
    一个project包含很多个Django app以及对它们的配置。技术上,project的作用是提供配置文件,比方说哪里定义数据库连接信息,安装的app列表,TEMPLATE_DIRS,等等。一个app是一套Django功能的集合,通常包括模型和视图,按Python的包结构的方式存在。例如,Django本身内建有一些app,例如注释系统和自动管理界面。app的一个关键点是它们很容易移植到其他project和被多个project复用。
  2. 如果你只是建造一个简单的Web站点,那么可能你只需要一个app就可以了;但如果是一个包含许多不相关的模块的复杂的网站,例如电子商务和社区之类的站点,那么你可能需要把这些模块划分成不同的app,以便以后复用。
  3. 但是,系统对app有一个约定:如果你使用了Django的数据库层(模型),你必须创建一个Django app。模型必须存放在apps中。因此,为了开始建造我们的模型,我们必须创建一个新的app。
  4. Django模型是用Python代码形式表述的数据在数据库中的定义。对数据库来说它等同于CREATE TABLE语句,只不过执行的是Python代码而不是SQL,而且还包含了比数据库字段定义更多的含义。Django用模型在后台执行SQL代码,并把结果用Python的数据结构来描述。
  5. 用Python和SQL来定义数据模型是不是有点多余?
    No.1: 自省(运行时自动识别数据库)会导致过载和有数据完整性问题。为了提供方便的数据访问API,Django需要以某种方式知道数据库层内部信息,有两种方式实现。第一种方式是用Python明确地定义数据模型,第二种方式是通过自省来自动侦测识别数据模型。
    No.2:首先,运行时扫描数据库会带来严重的系统过载。如果每个请求都要扫描数据库的表结构,或者即便是服务启动时做一次都是会带来不能接受的系统过载。第二,某些数据库,尤其是老版本的MySQL,并未完整地存储那些精确的自省元数据。
    No.3:把数据模型用代码的方式表述来让你可以容易对它们进行版本控制。这样,你很容易了解数据层的变动情况。
    No.4:SQL只能描述特定类型的数据字段。例如,大多数数据库都没有专用的字段类型来描述Email地址、URL。而Django的模型可以做到这一点。好处就是高级的数据类型带来更高的效率和更好的代码复用。
    No.5:SQL还有在不同数据库平台的兼容性问题。发布Web应用的时候,使用Python模块描述数据库结构信息可以避免为MySQL,PostgreSQL,SQLite编写不同的CREATE TABLE。
    当然,还有Python代码和数据库表的同步问题。如果你修改了一个Django模型,你要自己来修改数据库来保证和模型同步。Django提供了实用工具来从现有的数据库表中自动扫描生成模型。这对已有的数据库来说是非常快捷有用的。
  6. 书籍有书名和出版日期。它有一个或多个作者(和作者是多对多的关联关系[many-to-many]),只有一个出版商(和出版商是一对多的关联关系[one-to-many],也被称作外键[foreign key]):
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
website = models.URLField()
email = models.EmailField()
publication_date = models.DateField()

首先要注意的事是每个数据模型都是django.db.models.Model的子类。它的父类Model包含了所有必要的和数据库交互的方法,并提供了一个简洁漂亮的定义数据库字段的语法。信不信由你,这些就是我们需要编写的通过Django存取基本数据的所有代码。
每个模型相当于单个数据库表,每个属性也就是表中的一个字段。属性名就是字段名,它的类型(例如CharField)相当于数据库的字段类型(例如varchar)。
最后需要注意的是,我们并没有显式地为这些模型定义任何主键。除非你单独指明,否则Django会自动为每个模型生成一个自增长的整数主键字段id。每个Django模型都要求有单独的主键。
11. 现在的django1.7.7版本和djangobook上用的django有个比较麻烦的不同是,新建了一个project叫mysite之后,里面还有一个子文件夹也叫mysite,然后在/mysite/mysite里才有views啊,urls啊,settings啊,而manage.py是放在/mysite里的。所以我建templates和某个app文件夹的时候都要和manage.py摆在同一级,这样在settings.py的时候就会有点麻烦。
比如djangobook里说,我应该在INSTALLED_APPS里写上mysite.books,但是这样写根本找不到,我试着写成books之后,它就能找到了,validate通过:System check identified no issues。
并且我相信templates和app一定是要和manage.py摆在同一级目录下面的。我这样做是对的。
12. 关于Migrations!(New in Django 1.7!): Migrations are Django’s way of propagating changes you make to your models (adding a field, deleting a model, etc.) into your database schema.
No.1: Prior to version 1.7, Django only supported adding new models to the database; it was not possible to alter or remove existing models via the syncdb command (the predecessor to migrate).
No.2: 三个命令migrate, makemigrations, sqlmigrate。
No.3: migrate: applying migrations, as well as unapplying and listing their status.
No.4: makemigrations: creating new migrations based on the changes you have made to your models.
No.5: sqlmigrate: displays the SQL statements for a migration.
13. 我首先为books新建Migrations:python manage.py makemigrations,会输出:

Migrations for 'books':0001_initial.py:-Create model Author        -Create model Book        -Create model Publisher        -Add field publisher to book

因为在Book类里,把Publisher类作为了外键:publisher = models.ForeignKey(Publisher)。每次修改了books里的models.py都要重新makemigrations!!
接着,我就要对数据库进行修改啦!:python manage.py migrate,这会输出:

Operations to perform:Apply all migrations: books
Running migrations:Applying books.0001_initial... OK

这个时候,我检查一下MySQL,是不是里面有表了:mysql -u root -p,输入语句:SHOW TABLES IN django_db,显示:

Tables_in_django_db:books_author, books_book, books_book_authors, books_publisher, django_migrations.

基本数据访问

  1. 一旦你创建了模型,Django自动为这些模型提供了高级的Python API。
    No.1: 调用该对象的save()方法,将对象保存到数据库中。Django会在后台执行一条INSERT语句。
    No.2: 使用”Publisher.objects”属性从数据库取出出版商的信息,这个属性可以认为是包含出版上的记录集。这个属性有许多方法,这里调用Publisher.objects.all()方法获取数据库中Publisher类的所有对象。这个操作的幕后,Django执行了一条SQL SELECT语句。
    No.3: 如果需要一步完成对象的创建与存储至数据库,就使用objects.create()方法。
    No.4: 只需要为Publisher对象添加一个方法__unicode__()
    __unicode__()
    方法告诉Python如何将对象以Unicode的方式显示出来。
    No.5: 普通的python字符串是经过编码的,意思就是它们使用了某种编码方式(如ASCII, ISO-8859-1或者UTF-8)来编码。如果你把奇特的字符保存在一个普通的python字符串里,你一定要跟踪你的字符串是用什么编码的,否则这些奇特的字符可能会在显示或者打印的时候出现乱码。
    No.6: 但是Unicode对象并没有编码。它们用Unicode,一个一致的,通用的字符编码集。当你在python中处理unicode对象的时候,你可以直接将它们混合使用和互相匹配而不必去考虑编码细节。
    No.7: Django在其内部的各个方面都使用到了Unicode对象。模型对象中,检索匹配方面的操作使用的是unicode对象,视图函数之间的交互使用的是Unicode对象,模板的渲染也是用的unicode对象。通常我们不必担心编码是否正确,后台会处理的很好。
    No.8: 添加了__unicode__()
    方法,再验证的时候就不用再建Publisher啦!!因为已经save到数据库过啦!!!只有临时变量和import需要重来!!!
    No.9: 因为Publisher模型有一个自动增加的主键id,所以第一次调用save()还多做了一件事:计算这个主键的值并把它赋值给这个对象实例。接下来再调用save()将不会创建新的记录,而只是修改记录内容(也就是执行UPDATE SQL语句,而不是INSERT语句)。注意,并不是只更新修改过的那个字段,所有的字段都会被更新。这个操作有可能引起竞态条件,这取决于你的应用程序。
    No.10: 注意到Django在选择所有数据时并没有使用SELECT*,而是显式列出了所有字段。设计的时候就是这样:SELECT*会更慢,而且最重要的是列出所有字段遵循了python界的一个信条:明言胜于暗示。
    No.11: 然后,是objects属性。它被称为管理器。目前,我们只需了解管理器管理着所有针对数据包含、还有最重要的数据查询的表格级操作。所有的模型都自动拥有一个objects管理器,你可以在想要查找数据时使用它。
    No.12: 最后,还有all()方法,这个方法返回数据库中所有的记录,尽管这个对象看起来像一个列表,它实际上是一个QuerySet对象,这个对象是数据库中一些记录的集合。
    No.13:
>>> Publisher.objects.filter(name='Apress'):
SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE name = 'Apress';
(AND ...)

No.14:获取单个对象:>>> Publisher.objects.get(name=”Apress”),所以如果结果是多个对象,会导致抛出异常。
No.15: 数据排序:

>>> Publisher.objects.order_by("name"):
SELECT id, name, address, city, state_province, country, website
FROM books_publisher
ORDER BY name;

我们还可以指定逆向排序,在前面加一个减号前缀。”-name”。
在class Publisher里写类:

class Meta:ordering = ['name']

这样就能设置默认排序方法了。
No.16:限制返回的数据:

>>>Publisher.objects.order_by('name')[0]

返回第一个。[0:2]: OFFSET 0 LIMIT 2。
No.17: 不全改:

>>>Publisher.objects.filter(id=52).update(name='Apress Publishing')

一次更新多条记录:

>>>Publisher.objects.all().update(country='USA')

返回一个整型数值,表示受影响的记录条数。
No.18: 为了预防误删掉某一个表内的所有数据,Django要求在删除表内所有数据时显示使用all()。

>>> Publisher.objects.all().delete()

有条件删除:

>>> Publisher.objects.filter(country='USA').delete()

第6章 Django站点管理

对于某一类网站,管理界面是基础设施中非常重要的一部分。这是以网页和有限的可信任管理者为基础的界面,它可以让你添加,编辑和删除网站内容。一些常见的例子:你可以用这个界面发布博客,后台的网站管理者用它来润色读者提交的内容,你的客户用你给他们建立的界面工具更新新闻并发布在网站上,这些都是使用管理界面的例子。
但是管理界面有一问题:创建它太繁琐。当你开发对公众的功能时,网页开发是有趣的,但是创建管理界面通常是千篇一律的。你必须认证用户,显示并管理表格,验证输入的有效性诸如此类。
这一章是关于Django的自动管理界面。这个特性是这样起作用的:它读取你模式中的元数据,然后提供给你一个强大而且可以使用的界面,网站管理者可以用它立即工作。

django.contrib包

  1. Django自动管理工具是django.contrib的一部分。django.contrib是一套庞大的功能集,它是Django基本代码的组成部分,Django框架就是由众多包含附加组件(add-on)的基本代码构成的。
  2. 管理工具是本书讲述django.contrib的第一个部分。从技术层面讲,它被称作django.contrib.admin。django.contrib中有其它可用的特性,如用户鉴别系统(django.contrib.auth)、支持匿名会话(django.contrib.sessions)以及用户评注系统(django.contrib.comments)。这些我们将在第十六章详细讨论。目前,你只需要知道Django自带很多优秀的附加组件,它们都存在于django.contrib包里。
  3. 激活管理界面:就是默认已经在settings.py中INSTALLED_APPS和MIDDLEWARE_CLASSES中的那些项。
  4. 这个时候要Migrate到数据库中:python manage.py migrate,显示:
Operations to perform:Apply all migrations: admin, contenttypes, books, auth, sessions
Running migrations:Applying contenttypes.0001_initial... OKApplying auth.0001_initial... OKApplying admin.0001_initial... OKApplying sessions.0001_initial... OK

在浏览器输入:192.168.1.142/admin/就能进入管理界面。不过,先要建一个超级用户:

python manage.py createsuperuser

用户名默认是sen,邮箱我填的youngsend@sjtu.edu.cn。密码还是klm****。这个时候就能登陆了。

点击sen这个用户,进去有Password这一块,它说它用的algorithm是pbkdf2_sha256,迭代次数iterations是15000,salt不知是什么东西。。。hash是mmnbs+一长串*。

将你的Models加入到Admin管理中

  1. 有一个关键步骤我们还没做。让我们将自己的模块加入管理工具中,这样我们就能够通过这个漂亮的界面添加、修改和删除数据库中的对象了。新建books这个app时,就有一个空的admin.py了,现在在里面为Publisher, Author, Book三个模型都注册一番:
from django.contrib import admin
from books.models import Publisher, Author, Book
/*永远记得不管是python manage.py shell还是python manage.py runserver都是从/mysite这一级目录里开始查找的,所以绝不是from mysite.books.models去import,这是在/mysite/mysite下去找books。*/
admin.site.register(Publisher)
admin.site.register(Author)
admin.site.register(Book)

注册好之后就能在管理界面修改数据库了!!!!好方便,不用命令行向数据库添加数据了!!!

这里需要提到的一个特性是,管理工具处理外键和多对多关系(这两种关系可以在”Book”模块中找到)的方法。在Add book界面中,”外键”publisher用一个选择框显示,“多对多”字段author用一个多选框显示。点击两个字段后面的绿色加号,可以让你添加相关的记录。举个例子,如果你点击Publisher后面的加号,你将会得到一个弹出窗口来添加一个publisher。

Admin如何工作

  1. 当服务启动时,Django从urls.py引导URLconf,然后执行admin.autodiscover()。这个函数遍历INSTALLED_APPS配置,并且寻找相关的admin.py文件。如果在指定的app目录下找到admin.py,它就执行其中的代码。
  2. 管理工具其实就是一个Django应用程序,包含自己的模块、模板、视图和URLpatterns。

设置字段可选

  1. 为了设置email字段可选,只需要将Author这个Model的email属性改为:email = models.EmailField(blank=True)
  2. 为了消除歧义,Django生成CREATE TABLE语句自动为每个字段显式加上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
)
;

如果你留空一个字符型字段,它会为此插入一个空字符串,而不是NULL。但是,其它数据类型有例外:日期型、时间型和数字型字段不接受空字符串。在这种情况下,NULL是唯一指定空值的方法。在Django模块中,你可以通过添加null=True来指定一个字段允许为NULL。如果你想允许一个日期型(DateField, TimeField, DateTimeField)或数字型(IntegerField, DecimalField, FloatField)字段为空,你需要使用null=True和blank=True。也就是两个都要写。这样:

publication_date = models.DateField(blank=True, null=True)

不过好像只要写blank=True就行了!!!

使用python manage.py dbshell会自动转到mysql shell!!

自定义字段标签

  1. 字段名称并不总是贴切的。有些情况下,你可能想自定义一个标签。你只需在模块中指定verbose_name:
email = models.EmailField(blank=True, verbose_name='e-mail')

“修改后重启服务器,你会在author编辑页面中看到这个新标签”。第一次看到要重启哎!!!
2. 你不必把verbose_name的首字母大写,除非是连续大写,如USA。Django会自动适时将首字母大写,并且在其它不需要大写的地方使用verbose_name的精确值。
3. 列表默认地显示查询结果中对象的__unicode__()

4. 我们将为Author模块定义一个ModelAdmin类。这个类是自定义管理工具的关键,其中最基本的一件事情是允许你指定列表中的字段。还是在admin.py里:

class AuthorAdmin(admin.ModelAdmin):list_display = ('first_name', 'last_name', 'email')

admin.site.register(Author, AuthorAdmin)用AuthorAdmin选项注册Author。
5. 添加一个快速查询栏。向AuthorAdmin追加search_fields:

search_fields = ('first_name', 'last_name')

这个查询蛮强大的!!!参数的两个字段只是表示,我会在这两个属性里匹配字符串!!!
6. 为Book列表页添加一些过滤器:

class BookAdmin(admin.ModelAdmin):list_display = ('title', 'publisher', 'publication_date')list_filter = ('publication_date', )

注意有逗号!!!The value of ‘list_filter’ must be a list or tuple. 在外键字段试了一下,很有意思!!!再布尔型字段上也会很有用。
7. 另外一种过滤日期的方式是使用date_hierarchy选项:

date_hierarchy = 'publication_date'

修改好后,页面中的列表顶端会有一个逐层深入的导航条,它从可用的年份开始,然后逐层细分到月乃至日。date_hierarchy接受的是字符串,而不是元组,因为只能对一个日期型字段进行层次划分。
8. 最后,我们改变默认的排序方式,按publication date降序排列:

ordering = ('-publication_date', )

列表页面默认按照模块class Meta中的ordering所指的列排序。注意publication date列头现在有一个小箭头显示排序。

自定义编辑表单

  1. 通过fields这个选项,你可以排除一些不想被其他人编辑的fields,只要不选上不想被编辑的field即可。例如,在book数据库中,我们可以隐藏publication_date,以防止它被编辑:
fields = ('title', 'author', 'publisher')

如果你是一个编辑,不希望作者推迟出版日期的话,这个功能就很有用。。。。。。
2. 另一个常用的编辑页面自定义是针对多对多字段的。更好的办法是使用filter_horizontal

filter_horizontal = ('authors',)

刷新book编辑页面,你会看到Author区中有一个精巧的JavaScript过滤器,它允许你检索选项,然后将选中的authors从Available框移到Chosen框,还可以移回来。
3. 我们的book数据库膨胀到拥有数千条publishers的记录,以致于book的添加页面装载时间较久,因为它必须把每一个publisher都装载并显示在下拉框中。这时,使用raw_id_fields选项。它是一个包含外键字段的元组,它包含的字段将被展现成文本框,而不再是下拉框。

用户、用户组和权限

  1. 用户账号应该是通用的、独立于管理界面以外仍可以使用。但我们现在把它看做管理界面的一部分。在第十四章,我们将讲述如何把用户账号与你的网站(不仅仅是管理工具)集成在一起。
  2. user有三种权限:
    No.1 Active: 指定whether this user should be treated as active. Unselect this instead of deleting accounts!!!选择不选,而不是删除账号!!!
    No.2 Staff status: 指定whether the user can log into this admin site.
    No.3 Superuser status:指定that this user has all permissions without explicitly assigning them.
  3. 普通的活跃、非超级用户的管理用户可以根据一套设定好的许可进入。
  4. 当你创建一个用户时,它没有任何权限,该有什么权限是由你决定的。请注意,这些权限是定义在模块级别上的,而不是对象级别上的!!!!
  5. 权限管理系统也控制编辑用户和权限。如果你给某人编辑用户的权限,他可以编辑自己的权限,这种能力可能不是你希望的。赋予一个用户修改用户的权限,本质上就是把他变成了一个超级用户。
  6. 你也可以给组中分配用户。一个组简化了给组中所有成员应用一套许可的动作。组在大量用户特定权限的时候很有用。
  7. Django的管理界面对非技术用户要输入他们的数据时特别有用;事实上这个特性就是专门为这个实现的。
  8. 一个经典流程:
    No.1:负责这个报道的记者和要处理数据的开发者碰头,提供一些数据给开发者
    No.2:开发者围绕这些数据设计模型然后配置一个管理界面给记者
    No.3:记者检查管理界面,尽早指出缺少或多余的字段。开发者来回地修改模块
    No.4:当模块认可后,记者就开始用管理界面输入数据。同时,程序员可以专注于开发公众访问视图和模块。

管理界面不是终结者。过往许多年间,我们看到它被拆分、修改成若干个功能模块,而这些功能不是它所支持的。它不应成为一个公众数据访问接口,也不应允许对你的数据进行复杂的排序和查询。正如本章开头所说,它仅提供给可信任的管理员。

《The Django Book 2.0》中文版笔记相关推荐

  1. 学习django就看这本书了!django book 2.0中文版

    所属网站分类: 资源下载 > python电子书 作者:熊猫烧香 链接:http://www.pythonheidong.com/blog/article/29/ 来源:python黑洞网 dj ...

  2. vimtutor 中文版 - 笔记

    vimtutor 中文版 - 笔记 本文是将 vimtutor zh-cn 的内容进行的另存分享. 并自行提取了各章小结记录了笔记. vimtutor 笔记 第一讲小结 光标在屏幕文本中的移动既可以用 ...

  3. Django前端开发:项目笔记及链接

    下面的内容都是亲身实践得到,这里仅作记录. 参考B站视频理解Django 好评如潮Python Django全套教程,手把手教你从0搭建网站,带项目实战,学完可接单 记录一下,后面可待改进: 数据库员 ...

  4. Django项目搭建【学习笔记】

    Django项目搭建[学习笔记] 创建工程 安装 pip install django==1.11.11 -i https://pypi.tuna.tsinghua.edu.cn/simple 创建D ...

  5. mysql5.0镜像_Mysql5.0学习笔记(一)

    Mysql5.0学习笔记(一) -基本sql语句与支持字符集 1.登录 mysql -h localhost -u root 2.创建用户firstdb(密码firstdb)和数据库,并赋予权限于fi ...

  6. 《UG NX8.0中文版完全自学手册》一第1章 UG NX 8.0简介

    本节书摘来自异步社区<UG NX8.0中文版完全自学手册>一书中的第1章,作者 刘昌丽 , 周进,更多章节内容可以访问云栖社区"异步社区"公众号查看 第1章 UG NX ...

  7. Notepad++V6.8.1.0中文版

    安装教程: 1:下载Notepad++V6.8.1.0绿色版这款软件. 2:把下载来的软件将其保存到你指定的目录里面去,做好备份. 3:解压这款软件到桌面 4:双击notepad++.exe这个可执行 ...

  8. PTC Creo7.0中文版

    教程: 1.下载解压,得到PTC Creo 7.0镜像文件和文件 2.首先解压_SolidSQUAD_.7z,打开 3.用压缩软件WinRAR解压缩镜像文件,或者使用win10加载,双击Setup.e ...

  9. AviCAD 2020 Pro v20.0中文版

    安装教程 1.解压AviCAD 2020 Pro版文件包之后获得下面两个文件.我们双击打开"setup.exe"开始安装 2.点击"Next"下一步 3.勾选我 ...

  10. html5.0笔记,动易sf5.0标签笔记.doc

    动易sf5.0标签笔记 网站首页标签调用 动易SiteFactory 文章模型标签作者:动易网络 文章来源:灯火 点击数:1617 更新时间:2011-4-16 20:20:52标签名: {PE.La ...

最新文章

  1. 【组队学习】【28期】R语言数据科学
  2. javascript面向对象系列第一篇——构造函数和原型对象
  3. java为什么打不开jar_带你上手阿里开源的 Java 诊断利器:Arthas
  4. xpath IE 7
  5. Winforn中导入Excel并显示然后获取多选框选中的内容
  6. EF中Take和Skip的区别
  7. freemark循环map_freemarker中循环map根据key值得value 报错
  8. java.net.ConnectException: Connection refused: no further information
  9. java 把图片插入窗体,JAVA JFrame窗体添加背景图像的两种方法
  10. 让你又爱又恨的推荐系统--程序猿篇
  11. 5-35 有理数均值 (20分)
  12. Exchange Server 2016 之三:邮箱角色部署
  13. HCIE-Security Day4:安全策略和状态检测
  14. 安装FeHelper插件
  15. Canvas画布、SVG图片
  16. python如何识别特殊字符_Python怎么判断过滤特殊字符
  17. invalid vcs root mapping 怎么解决_一加黑鲨华硕OPPO等手机root后微信指纹支付不可用怎么解决...
  18. Ubuntu修改桌面分辨率
  19. RK3588 CPU GPU DDR NPU定频和性能模式设置
  20. 获取Mac地址getMacAddress

热门文章

  1. 10.1 Python图像处理之边缘算子-Sobel算子、Roberts算子、拉普拉斯算子、Canny算子、Prewitt算子、高斯拉普拉斯算子
  2. android Textview属性细节以及EditText属性
  3. Matlab求矩阵均值
  4. Opencv3 core模块解析之convertTo
  5. ​​spss13.0 附安装教程
  6. layui 表单验证案例
  7. 用java写一个博客网站
  8. 在MinGW中构建GCC交叉编译器和GDB交叉调试器
  9. Java编程——九九乘法表
  10. 数据挖掘技术的来源 历史 研究内容及常用技术