这一节我们将继续一个创建网络收藏夹应用,并学习视图、模型以及模板的处理过程。

  Django是一个MVC开发框架,但是它的控制器对应的为view,而视图对应为模板(template),模型对应model,所以Django也成为MTV框架。

  URLS和视图函数(Views)

  view(视图函数)通过生成页面来响应某个用户请求,首先我们在项目中先创建一个应用,应用是包含视图与数据模型的容器,在django_boookmarks目录下运行下面的命令:

$ python manage.py startapp bookmarks

  创建应用的语法与创建项目的语法类似。运行上述命令之后,Django会自动在bookmarks目录下生成下面的文件。

  • __init__.py 表明这是一个包
  • views.py  包含视图函数
  • models.py 包含数据模型

  接下来,创建主页视图:

from django.http import HttpResponse

def main_page(request):
output = '''
<html>
<head><title>%s</title></head>
<body>
<h1>%s</h1><p>%s</p>
</body>
</html>
''' % (
'Django Bookmarks',
'Welcome to Django Bookmarks',
'Where you can store and share bookmarks!'
)
return HttpResponse(output)

  这段代码非常的简洁,首先,我们从Django.http 中导入HttpResponse类,通过这个类我们来生成响应页面。接着我们定义了一个视图函数main_page(),使用request作为参数,request中包含了一些用户的输入以及其他信息,如request.GET,request.POST,request.COOKIES等等。最后我们通过HttpResponse生成页面响应返回。

  定义了视图函数之后,就需要再定义URL。

  打开urls.py,在其中给主页视图添加URL配置。

from django.conf.urls.defaults import *
from bookmarks.views import * urlpatterns = patterns('',
(r'^$', main_page),
)

  也来分下下这段代码,首先从django.conf.urls.defaults中导入定义URLS的相关函数,接着从bookmarks.views中导入所有的视图函数,最后定义URL表,将r'^$'映射到视图函数main_page。

  r'^$'是一个正则表达式,r代表原始字符串,表示字符串中的特殊字符不会进行转义,^代表字符串的开头,$代表字符串的结尾。所以^$代表了空字符串。python中跟正则表达式相关的模块是re,具体用法可以查看官方文档。

  接下来在浏览器中输入http://127.0.0.1:8000/即可看到创建的主页。

  Django的工作流程如下所示:

  • 当用户请求http://127.0.0.1:8000/时,Django会在urls.py中查找匹配的URL,匹配通过正则表达式完成。
  • 如果Django找到匹配的URL,就会调用相应的视图函数,视图函数就收用户浏览器提交的数据信息,然后生成响应页面返回给用户。
  • 如果Django没有找到匹配的URL,Django将抛出404异常,同时展示Page Not Found页面。在调试模式下,Django会打印丰富的帮助信息,当然,在部署环境中饭可以关闭调试模式。

  数据模型

  现在几乎所有的Web站点都会使用数据库管理保存数据,数据库现在已经是网站的重要组成部分。接下里,我们将使用数据库管理用户账号与网络收藏夹。如果你习惯了使用SQL语句对处理数据库,那么你将发现Django处理数据库的方式不太一样,Django是通过Python类对数据库进行管理的。

  下面通过例子来讲解,对于我们的网路收藏夹,我们需要在数据库中保存如下信息:

  • User(ID,username,password,email)
  • Links(ID,URL)
  • Bookmarks(ID,title,user_id,link_id)

  为了将上面的数据表设计转换成Python代码,需要再bookmarks目录下的models.py进行编辑,models.py用来保存数据模型。

  ♥Link数据模型

  打开bookmarks/models.py,输入以下代码:

from django.db import models
class Link(models.Model):
url = models.URLField(unique=True

  models模块包含了一些用来定义数据模型的类,我们定义了一个Link类,它继承自models.Model,Model是所有模型类的基类,Link类定义了一个url字段,这个字段必须是唯一的。

  models.URLField只是Django提供的众多数据字段类型之一,下面是其中一些常用的字段类型。

  字段类型      描述

  IntegerField    整型
  TextField      文本类型

  DateTimeField     日期时间类型

  EmailField     电子邮件类型

  URLField       URL类型

  FielField          文件类型  


  为了使用这个模型,需要现在settings.py中的INSTALLED_APPS中添加刚刚创建的应用名:

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

  接下来使用下面的命令在数据库中创建相应的数据表:

$ python manage.py syncdb

  注意,每当我们添加一个数据模型,都需要执行上面的命令。Django会自动分析Link模型,然后生成相应的SQL语句,并执行这些语句生成对应的数据表,Django会自动给每个模型添加id字段。这个字段是整个数据表的主键。

  Django的数据库API不仅仅能够生成数据表,还可以对数据表进行增删改操作,接下来,我们将通过python交互窗口来探索这些功能,通过下面这条命令打开交互窗口:

$ python manage.py shell

  这个命令窗口与标准的窗口不太一样,首先,打开这个窗口之前,Django会将当前项目的路径加入到sys.path中,这样就可以自动导入当前项目中的模块,其次有个特殊的环境变量可以保存我们当前使用的settings.py的路径。所以,每当我们需要使用命令窗口与当前项目交互时,使用上面的命令即可。

  接下来,导入models模块中的所有内容:

>>> from bookmarks.models import *

  添加一条新的URL,并保存到数据库中:

>>> link1 = Link(url='http://www.packtpub.com/')
>>> link1.save()
>>> link2 = Link(url='http://www.example.com/')
>>> link2.save()

  只有当调用save方法的时候,数据才会保存到数据库中,没调用之前,数据都只是缓存在内存中,如果关闭命令窗口,数据将会丢失。  

  数据表中的字段都会转换成对象的属性,通过下面的方法可修改Link的URL。

>>> link2.url
'http://www.example.com/'
>>> link2.url = 'http://www.google.com/'
>>> link2.save()

  通过下面的方法可以获取所有的Link对象。  

>>> links = Link.objects.all()
>>> for link in links:
... print link.url
...
http://www.packtpub.com/
http://www.google.com/

  通过下面的方法获取指定ID的Link

>>> Link.objects.get(id=1)
<Link: Link object>

  最后使用下面方法删除一条Link:

>>> link2.delete()
>>> Link.objects.count()
1

  输出结果1表明现在只剩一条Link,注意上面我们所有的操所都不是通过SQL来执行的,Django提供了几乎所有的数据接口,实际上上面的所有命令都是先转换成SQL再执行的。这样做的好处是非常明显的:

  • 不需要非常了解SQL语句
  • Django透明的处理Python对象与数据表的转换,你只需要与Python打交道。
  • 开发者不需要担心不同数据库而导致的SQL差异。不管使用哪种数据库,Django提供的接口都是一样的。
  ♥User数据模型

  接下来创建用户数据模型,幸运的是,Django已经给开发者提供了一个内置的用户数据模型,它位于django.contrib.auth.models中,模型名为User。

>>> from django.contrib.auth.models import User
>>> User.objects.all()
[<User: root>]

  可以发现数据表中已经包含了一个用户,这个用户是我们第一次执行syncdb时生成的用户。

  使用dir()函数可以查看User模型的字段。

>>> user = User.objects.get(id=1)
>>> dir(user)

  结果得到一个属性列表,其中包含了username,email以及password属性,这些刚好满足我们的要求,所以直接使用就行了。

  ♥Bookmark数据模型

  最后我们定义Bookmark数据模型,User与Bookmark以及Link与Bookmark之间的关系都是一对多的关系。在数据表中的表现就是外键,所以在Bookmark数据模型中我们定义两个外键:

from django.contrib.auth.models import User
class Bookmark(models.Model):
title = models.CharField(maxlength=200)
user = models.ForeignKey(User)
link = models.ForeignKey(Link

  接着执行python manage.py syncdb即可。

  通过下面的命令可以得到Django实际上是如何处理外键的SQL语句:

$ python manage.py sql bookmarks

  结果为:

BEGIN;
CREATE TABLE "bookmarks_bookmark" (
"id" integer NOT NULL PRIMARY KEY,
"title" varchar(200) NOT NULL,
"user_id" integer NOT NULL REFERENCES
"auth_user" ("id"),
"link_id" integer NOT NULL REFERENCES
"bookmarks_link" ("id"),
);
CREATE TABLE "bookmarks_link" (
"id" integer NOT NULL PRIMARY KEY,
"url" varchar(200) NOT NULL UNIQUE
);
COMMIT;

  注意,Django也自动给Bookmark添加了id属性。

  主页模板

  在前面的部分,我们通过将HTML硬编码到代码中,创建了一个简单的应用主页,这样有很多缺点:

  • 优秀的软件工程实践一直强调UI与业务逻辑的分离,因为这样才会增强代码的重用性。而在Python代码中编辑HTML违反了这一原则。
  • 修改嵌套在Python中的HTML代码需要了解Python知识,但是作为前端开发者,很多都不了解Python,所以这样做也不实际。
  • 在Python中处理HTML代码是非常冗长乏味的工作。

  因此,最好将Django视图与HTML代码分离开来,幸运的是,Django提供了这样一个机制,那就是模板系统。

  模板系统的机制很简单,它将HTML代码保存在模板中,在这个模板中有一些占位符,占位符的内容可以被视图所产生的动态内容所替换,当生成一个页面时,视图函数加载模板,然后将动态产生的值传递给它,然后模板将占位符替换成对应的内容,最终生成页面返回。

  为了更好的理解这一机制,我们修来之前创建的main_page视图,首先在当前项目中创建一个templates目录,然后打开settings.py文件,找到TEMPLATES_DIRS变量,将templates的路径加到这里,如果你想支持跨平台,那就使用下面的代码:

import os.path
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates'),
)

  接下来在templates目录中创建main_page.html:

<html>
<head>
<title>{{ head_title }}</title>
</head>
<body>
<h1>{{ page_title }}</h1>
<p>{{ page_body }}</p>
</body>
</html>

  模板的结构与HTML很相似,但是其中包含了一些特殊的语法,模板变量,例如{{ head_title }}表明它的内容将会被head_title的值所替换。模板变量的总是被两个花括号所包围。

  接下来,再修改bookmarks/views.py中内容:

from django.http import HttpResponse
from django.template import Context
from django.template.loader import get_template
def main_page(request):
template = get_template('main_page.html')
variables = Context({
'head_title': 'Django Bookmarks',
'page_title': 'Welcome to Django Bookmarks',
'page_body': 'Where you can store and share bookmarks!'
})
output = template.render(variables)
return HttpResponse(output)

  为了加载模板,我们使用了 get_template方法,它位于django.template.loader中,这个方法使用模板名作为参数,返回一个template对象。通过创建一个Context对象,来设置模板中的变量值,Context使用一个字典作为参数,字典使用模板变量为键,对应的值为变量的实际值。使用template对象的render方法替换模板中的变量值,最后通过HTTPResponse将得到输返回。

  这样做的好处是非常明显的,我们不再需要在Python代码中处理HTML代码了,HTML部分可以直接交给前端工作者处理了。

  生成用户页面

  前面我们介绍了视图,模板以及数据模型,最后,我们将使用这些知识创建一个用户页面,这个页面将展示属于这个用户的所有Bookmarks。

  1.设计URL

  这个视图的URL格式为:user/username,username是书签所有者的用户名,这个URL与我们之前添加的URL不太一样,它包含了一个动态部分,我们需要使用正则表达式来表示这个URL,编辑urls.py,

urlpatterns = patterns('',
(r'^$', main_page),
(r'^user/(\w+)/$', user_page),
)

  \w代表任意一个字母数字或者下划线,+代表一个或者多个。

  2.创建视图函数

  打开bookmarks/views.py视图,添加如下代码:

from django.http import HttpResponse, Http404
from django.contrib.auth.models import User
def user_page(request, username):
try:
user = User.objects.get(username=username)
except:
raise Http404('Requested user not found.')
bookmarks = user.bookmark_set.all()
template = get_template('user_page.html')
variables = Context({
'username': username,
'bookmarks': bookmarks
})
output = template.render(variables)
return HttpResponse(output)

  跟之前的视图不太一样,这个视图提供了第二个参数,这个参数是从url中获取到的。通过User.object.get()函数获取用户名为username的用户,如果没找到或者找到多个同名用户,就抛出404异常。为了获取指定用户所拥有的bookmarks,我们使用user对象的bookmark_set属性,Django会自动检查不同模型之间的关系,然后生成这样的属性。

  3.设计模板

  在templates目录下创建user_page.html:

<html>
<head>
<title>Django Bookmarks - User: {{ username }}</title>
</head>
<body>
<h1>Bookmarks for {{ username }}</h1>
{% if bookmarks %}
<ul>
{% for bookmark in bookmarks %}
<li><a href="{{ bookmark.link.url }}">
{{ bookmark.title }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No bookmarks found.</p>
{% endif %}
</body>
</html>

  这个模板比之前那个更加复杂,。它还是用了if标签以及for循环标签,bookmarks变量也是个列表对象。if标签可以判断变量是否包含了数据,如果有,则输出下面的信息,如果没有,则输出else下面的语句。for标签用来循环一个列表。

  最后在浏览器中输入http://127.0.0.1:8000/user/your_username,就得到了最后的结果。虽然模板成功展示了,但是现在用户还没有对应的bookmark数据。我们可以通过交互窗口创建一写bookmarks。

  运行python manage.py shell

  然后执行下面的命令:

>>> from django.contrib.auth.models import User
>>> from bookmarks.models import *
>>> user = User.objects.get(id=1)
>>> link = Link.objects.get(id=1)
>>> user.bookmark_set.all()
[]
>>> bookmark = Bookmark(
... title='Packt Publishing',
... user=user,
... link=link
... )
>>> bookmark.save()
>>> user.bookmark_set.all()
[<Bookmark: Bookmark object>]

  这样,页面中就会展示bookmarks信息了。

  

Django Web开发【3】创建网络收藏夹的更多相关文章

  1. Django web开发【5】 实现标签功能

    标签tag在很多web2.0应用中都很常见,标签其实就是关联某些信息的一个关键字.打标签实际上就是给内容分配标签的过程,它通常由作者或者用户实现.标签之所有这么流行是因为它允许用户对自己创建的博客.图 ...

  2. Django Web开发【1】Django简介

    前言 看完<Django Book>之后, 总想找个实例来实战开发下,无奈国内Django的书籍相当少,只能从英文书籍中吸取养料,偶然之后得到Learning Website Develo ...

  3. Django Web开发指南笔记

    Django Web开发指南笔记 语句VS表达式 python代码由表达式和语句组成,由解释器负责执行. 主要区别:表达式是一个值,它的结果一定是一个python对象:如:12,1+2,int('12 ...

  4. Django web 开发指南 no such table:

    在学习django web开发指南时,发布新博客点击save后会有error提示:no such table balabalabala... 百度了一下说重新运行manage.py syncdb 就可 ...

  5. Django Web开发学习笔记(1)

    一.Python的标准类型 (1)bool型 >>> bool("") False >>> bool(None) False >>& ...

  6. Django Web开发【4】 用户注册与管理

    几乎所有的网站都提供了用户注册与管理功能,这一节,我们将讲解如何利用Django自身提供的用户认证系统实现用户注册与管理功能. 会话认证 在上一节中,我们学习了User数据模型,并用它来保存用户信息, ...

  7. Django web编程1 -- 创建项目和应用

    python:3.7.2 Django:2.1.7 1.创建虚拟环境 虚拟环境是系统的一个位置,可以在其中安装包,并将其与其他python包隔离. 创建目录,命名为learning_log,并切换到这 ...

  8. [python] python django web 开发 —— 15分钟送到会用(只能送你到这了)

    1.安装python环境 1.1 安装python包管理器: wget https://bootstrap.pypa.io/get-pip.py sudo python get-pip.py   1. ...

  9. Django Web开发【2】Django入门

    配置开发环境 1.安装Python,我使用的是centos 6.0,python版本为2.6.6 2.安装Django,Django版本为1.3.5 在Django官网下载对应版本之后,解压压缩包,进 ...

随机推荐

  1. oracle&&Sqlserver获取表名列名主键及数据类型

    SQlserver获得列名,列类型,列类型长度,scale,prec等数据类型(syscolumns,systypes,sysobjects均为视图) select a.name as colname ...

  2. html系列教程--ol ul li

    <li> 标签:配合ol,ul实现有序,无序列表以及导航实现. demo: <ol>    <li>Coffee</li>    <li>T ...

  3. Android API Level在11前后及16之后时Notification的不同用法

    作为刚入门Android的小白,最近在按照郭大神的<第一行代码>在练习,在用到Notification时遇到了一些问题,网上资料比较零散,我这里做了一个总结分析给各位,若有错误,恳请指正~ ...

  4. ora-06502

    执行一个存储过程时报这个错误 ORA-06502: PL/SQL: 数字或值错误 发现是定义的字符串的缓冲区太小,赋给字符串的值又太大 修改varchar2(20)  →   varchar2(200 ...

  5. c#导出文件,文件名中文乱码解决方法。

    public string clFielName(string fileName) { System.Web.HttpContext curContext = System.Web.HttpConte ...

  6. JAVA G1收集器 第11节

    JAVA G1收集器 第11节 上两章我们讲了新生代和年老代的收集器,那么这一章的话我们就要讲一个收集范围涵盖整个堆的收集器——G1收集器. 先讲讲G1收集器的特点,他也是个多线程的收集器,能够充分利 ...

  7. 我本人一直以来犯的错误,在看了《Think In Java》后才抓了出来(转)

    也许你是只老鸟,也许你的程序编的很精,但是,在你的程序生活,你也许没有注意到一些“常识性”的问题,因为有些时候我们不需要去注意,我们的程序 照样能够运行得飞快,但是如果那天有一个无聊的人问你一个像这样 ...

  8. 最近做OpenWrt的总结

    用到了哪些东西 需要在OpenWrt上开发一个客户端,用C语言写还比较方便,最开始在linux上跑,后面移植到路由器上,做成ipk.除了稍微修改了下Makefile,其他的什么都没改. 因为需要做个配 ...

  9. Java提高学习之Object类详解(1)

    转自:http://www.importnew.com/10304.html 问:什么是Object类? 答:Object类存储在java.lang包中,是所有java类(Object类除外)的终极父 ...

  10. js返回值

    看下js变量.作用域.内存文档. 1. <script type="text/javascript"> function c(){ return 23; } var a ...