最近在整理之前的笔记,这是之前自学Django时记录的,梳理以备查阅。教程看的是The Django Book中文版
安装
基本环境
- Ubuntu14.04 LTS
- Django1.7.1
- Python2.7.6
| 1 | $> pip install Django==1.7.1 | 
开始项目
创建项目
| 1 | $> django-admin.py startproject mysite(项目名) | 
- init.py :让 Python 把该目录当成一个开发包 (即一组模块)所需的文件。 这是一个空文件,一般你不需要修改它。
- manage.py :一种命令行工具,允许你以多种方式与该 Django 项目进行交互。 键入python manage.py help,看一下它能做什么。 你应当不需要编辑这个文件;在这个目录下生成它纯是为了方便
- settings.py :该 Django 项目的设置或配置。 查看并理解这个文件中可用的设置类型及其默认值。 - 1 
 2
 3- #修改配置项: 
 LANGUAGE_CODE = 'zh-cn'
 TIME_ZONE = 'Asia/Shanghai'
- urls.py:Django项目的URL设置。 可视其为你的django网站的目录。 目前,它是空的。 
- wsgi.py:Django工程入口
启动开发Web服务器
| 1 | #首次启动先执行 | 
视图——View & URLconf
视图
 创建视图文件:mysite/mysite/views.py1
2
3
4
5from django.http import HttpResponse
#视图函数
def hello(request):
  return HttpResponse("Hello world")
每个视图函数至少要有一个参数,通常被叫作request。 这是一个触发这个视图、包含当前Web请求信息的对象,是类django.http.HttpRequest的一个实例。在这个示例中,我们虽然不用request做任何事情,然而它仍必须是这个视图的第一个参数。
URLconf
 URLconf是为了绑定视图函数和URL,当使用django-admin.py startproject创建项目时,该脚本会自动创建一份 URLconf(即urls.py)
 在添加URLconf前,需要告知Django URLconf的根目录路径。mysite/settings.py中添加ROOT_URLCONF = 'mysite.urls'1
2
3
4
5
6from django.conf.urls.defaults import *
from mysite.views import hello               #import视图函数
urlpatterns = patterns('',
	('^hello/$', hello),
)
Django处理请求过程
- 进来的请求转入/hello/
- Django通过mysite/settings.py里的ROOT_URLCONF配置来决定根URLconf.
- Django在URLconf中的所有URL模式中,查找第一个匹配/hello/的条目。
- 如果找到匹配,将调用相应的视图函数(mysite/views.py里的函数)
- 视图函数返回一个HttpResponse
- Django转换HttpResponse为一个适合的HTTP response, 以Web page显示出来(带有HTTP头和body的Web Response)
模板——template
 模板是Django中页面展示部分,包含HTML/CSS/JS等内容。
 在mysite/settings.py中指定模板路径1
2
3
4
5import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
TEMPLATE_DIRS = (
	os.path.join(BASE_DIR, 'templates'),
)
完整Django开发流程
- 编写模板文件 
 在项目文件夹下创建模板文件夹:- mysite/templates- 1 
 2
 3
 4
 5- <html> 
 <body>
 It is now {{nowTime}}.
 </body>
 </html>
- 创建视图函数 
 在- mysite/views.py中创建视图函数。此为最基础的方法- 1 
 2
 3
 4
 5
 6
 7
 8- from django.template.loader import get_template 
 from django.template import Context
 def hourTemplate(request):
 now = datetime.datetime.now()
 temp = get_template('hourTemplate.html') #创建template对象
 html = temp.render(Context({'nowTime': now})) #创建Context和调用render()方法
 return HttpResponse(html)
- 快捷调用模板:render_to_response 
 在视图函数中可以使用快捷调用模板的函数render_to_response,此方法较为常用。- 1 
 2
 3
 4- from django.shortcuts import render_to_response 
 def hourTemplate(request):
 now = datetime.datetime.now()
 return render_to_response('hourTemplate.html', {'nowTime': now})
- 设置URL 
 在- mysite/urls.py中添加URLconf- 1 
 2
 3
 4
 5- from mysite.views import hourTemplate 
 urlpatterns = patterns(
 '',
 (r'^hourTemplate/$', hourTemplate),
 )
模板继承
 模板还能使用标签(if/else、for、ifequal/ifnotequal),具体详见The Django Book 第四章
 模板还有一个非常重要的功能:模板继承,为了减少共用页面所引起的重复和冗余代码,Django解决此问题的首选方法是使用模板继承。下面通过一个实例加以说明。
 模板目录下有三个模板文件templates/base.html、now.html、later.html
- base.html——基础模板,每个 - block name必须唯一- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- <html> 
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 <title>{% block title %}{% endblock %}</title>
 </head>
 <body>
 <div align='center'>
 <h1 id="content1">Template Inherit</h1>
 {% block content %}{% endblock %}
 {% block footer %}
 <hr>
 <p>Thank for visitting my website</p>
 {% endblock %}
 </div>
 </body>
 </html>
- now.html - 1 
 2
 3
 4
 5
 6- {% extends 'base.html' %} 
 {% block title %}This is now.html{% endblock %}
 {% block content %}
 <p>Now time is {{ nowTime }} </p>
 {% endblock %}
- later.html - 1 
 2
 3
 4
 5
 6- {% extends 'base.html' %} 
 {% block title %}This is later.html{% endblock %}
 {% block content %}
 <p>In {{ hours }} hour(s) later, it will be {{ laterTime }} </p>
 {% endblock %}
- 视图函数——mysite/views.py - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17- import datetime 
 from django.http import Http404
 from django.shortcuts import render_to_response
 def now(request):
 """template inherit now"""
 now = datetime.datetime.now()
 return render_to_response('now.html', {'nowTime': now})
 def later(request, hourNum):
 """template inherit later"""
 try:
 hours = int(hourNum)
 except Exception, e:
 return Http404, e
 hourLater = datetime.datetime.now() + datetime.timedelta(hours=hours)
 return render_to_response('later.html', {'hours': hours, 'laterTime': hourLater})
- URLconf配置 - 1 
 2
 3
 4- urlpatterns = patterns('', 
 url(r'^now/$', now),
 url(r'^later/(\d{1,2})/$', later),
 )
模型
Django若需要与数据库交互则使用模型Model。模型负责数据库层面,app才可使用模型,project不行,所以需要先创建app。
创建app
| 1 | $> python manage.py startapp appname | 
Django配置MySQL数据库
 mysite/setting.py(NAME中的数据库需要预先创建)1
2
3
4
5
6
7
8
9
10DATABASES = { 
	'default': {
		'ENGINE': 'django.db.backends.mysql',
		'NAME': 'books',
		'USER': 'root',
		'PASSWORD': 'moguoliang',
		'HOST': '127.0.0.1',
		'PORT': '3306',
	} 
}
 测试Django连接数据库1
2
3$> python manage.py shell
from django.db import connection
cursor = connection.cursor()
编写数据库模型
 mysite/books/models.py1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22from 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=30)
    website = models.URLField()
class Author(models.Model):
    firstName = models.CharField(max_length=30)
    lastName = models.CharField(max_length=40)
    email = models.EmailField(blank=True,verbose_name='e-mail')	#允许空白
class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publicationDate = models.DateField(blank=Ture, null=True)
安装&测试模型
安装模型
 mysite/setting.py1
2
3INSTALLED_APPS = (
   'books',
)
检查模型有效性
| 1 | $> python manage.py check | 
执行模型
 models.py变更后都要执行makemigrations和migrate,sqlmigrate仅用来查看SQL语句1
2
3
4
5
6
7
8# 生成migrate
$> python manage.py makemigrations books 
#查看SQL语句
$> python manage.py sqlmigrate books 0001 
#执行SQL语句
$> python manage.py migrate
#python manage.py syncdb     #旧版本
插入数据
使用Django提供的Python Shell进行插入数据测试。插入数据有两种方法:1. 逐条插入数据;2. 批量插入数据
- 逐条插入 - 1 
 2
 3
 4
 5- $> python manage.py shell 
 >>> from book.models import Publisher
 >>> p1 = Publisher(name='test', address='GaoXinYuan', city='Shenzhen', state_province='Guangdong', country='China', website='http://10.0.2.15:8000')
 >>> p1.save()
- 批量插入——objects.create() - 1 
 2
 3
 4
 5
 6- $> python manage.py shell 
 >>> from book.models import Publisher
 >>> 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
- 操作数据库的常用函数方法 - Plulisher.objects.create() 插入数据
- Publisher.objects.all() 显示所有数据
- Publisher.objects.filter(name=’Apress’) 过滤显示数据
- Publisher.objects.get(name=”Apress”) 获取单个对象
- Publisher.objects.order_by(“name”) 数据排序
- Publisher.objects.order_by(“-name”) 逆向数据排序
- Publisher.objects.filter(country=”U.S.A.”).order_by(“-name”) 连锁查询
- Publisher.objects.order_by(‘name’)[0] 限制返回数据(limit 1)
- Publisher.objects.filter(id=52).update(name=’Apress Publishing’) 更新数据
- Publisher.objects.filter(country=’USA’).delete() 删除数据
 
Django admin管理站点
- 创建管理员用户 - 1 - $> python manage.py createsuperuser 
- 重置superuser密码 - 1 - $> python manage.py changepassword username 
- 检查 - mysite/urls.py- 1 - url(r'^admin/', include(admin.site.urls)), 
- 将模型model添加进admin管理—— - mysite/book/admin.py- 1 
 2
 3
 4
 5
 6- from django.contrib import admin 
 from book.models import Publisher, Author, Book
 # Register your models here.
 admin.site.register(Publisher)
 admin.site.register(Author)
 admin.site.register(Book)
表单
获取request对象数据
 视图函数hello(request)中的第一个参数是一个HttpRequest对象,我们可以通过此对象获取一些有用信息。1
2
3from django.http import HttpResponse
    def hello(request):
       return HttpResponse("Hello world")
HttpRequest对象包含当前请求URL的一些信息:
- request.path:除域名以外的请求路径,以正斜杠开头。例如:”/hello/“
- request.get_host():主机名(比如,通常所说的域名)。 例如:”127.0.0.1:8000” or “www.example.com"
- request.get_full_path():请求路径,可能包含查询字符串。例如:”/hello/?print=true”
- request.is_secure():如果通过HTTPS访问,则此方法返回True; 否则返回False。
HTTP Header信息
 request.META是一个Python字典,包含了所有本次HTTP请求的Header信息
 利用request.META获取HTTP Header信息:1
2
3def ua_display_good2(request):
   ua = request.META.get('HTTP_USER_AGENT', 'unknown')
   return HttpResponse("Your browser is %s" % ua)
利用模板列出所有HTTP Header信息实例
- 创建模板—— - mysite/templates/displayHeaderTemp.html- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- <html> 
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 <title>{% block title %}{% endblock %}</title>
 <body>
 <ul>
 {% for tkey, tvalue in headDict.iteritems %}
 <li>{{tkey}}: {{tvalue}}</li>
 {% endfor %}
 </ul>
 </body>
 </head>
 </html>
- 添加视图函数—— - mysite/views.py- 1 
 2
 3
 4- from django.shortcuts import render_to_response 
 def displayHeaderTemp(request):
 return render_to_response('displayHeaderTemp.html', {'title': 'displayHeaderTemplate', 'headDict': request.META})
- 配置URL—— - mysite/urls.py- 1 
 2
 3
 4- from mysite.views import displayHeaderTemp 
 urlpatterns = patterns(
 url(r'^displayHeaderTemp/$', displayHeaderTemp),
 )
获取表单提交的数据
- request.GET:获取用户通过GET方法提交的表单数据(参数URL中可见)
- request.POST:获取用户通过POST方法提交的表单数据
实例一
用户通过searchForm页面GET方法提交表单数据,跳转到search页面,通过request.GET获取用户提交数据并在页面显示
- 创建模板—— - templates/searchForm.html- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- <html> 
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 <title>search form</title>
 </head>
 <body>
 <form action="/search/" method="get" accept-charset="utf-8">
 <input type="text" name="q" value="">
 <input type="submit" value="Search →">
 </form>
 </body>
 </html>
- 创建视图—— - books/views.py
 - books/views.py是在books这个app里的视图,非- mysite/views.py- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- from django.shortcuts import render, render_to_response 
 from django.http import HttpResponse
 def searchForm(request):
 return render_to_response('searchForm.html')
 def search(request):
 if 'q' in request.GET:
 message = "You search for: %s" % request.GET['q']
 else:
 message = "You sumit an empty form."
 return HttpResponse(message)
- 配置URL—— - mysite/urls.py
 因为searchForm会跳转到search,url配置中必须有search及相对于的视图函数- 1 
 2
 3
 4
 5- from books import views 
 urlpatterns = patterns('',
 url(r'^searchForm/', views.searchForm),
 url(r'^search/', views.search),
 )
实例二
利用Django提交表单发送邮件
- 邮件设置—— - mysite/setting.py- 1 
 2
 3
 4
 5
 6
 7
 8- #email setting 
 #EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
 EMAIL_HOST = 'smtp.163.com'
 EMAIL_PORT = 25
 EMAIL_HOST_USER = 'xxxxx@163.com'
 EMAIL_HOST_PASSWORD = '**********'
 EMAIL_USE_TLS = True
 #EMAIL_SUBJECT_PREFIX = u'Django邮件测试'
- 测试利用Django发送邮件 
 返回- 1则成功,- 0则失败- 1 
 2
 3- $> python manage.py shell 
 >>> from django.core.mail import send_mail
 >>> send_mail('DjangoMail','test','autodeploy@163.com', ['221bmogl@gmail.com'], fail_silently=True)- send_mail()函数参数解释: - send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None,auth_password=None, connection=None)
- subject, message, from_email and recipient_list 这四个参数是必须的。 
- subject: 字符串,表示邮件标题。 
- message: 字符串,表示邮件内容。
- from_email: 字符串,表示发件邮箱。
- recipient_list: 字符串列表,列表中每个成员都是一个邮箱地址,而且每个收件人都会在 “收件人/To:” 栏看到出现在 recipient_list 中的其他收件人。
- fail_silently: (可选)布尔值。为 False 时, send_mail 会抛出 smtplib.SMTPException 异常。 smtplib 文档列出了所有可能的异常。 这些异常都是 SMTPException 的子类。
- auth_user: (可选)SMTP服务器的认证用户名。没提供该参数的情况下,Django会使用 EMAIL_HOST_USER 配置项的设置。
- auth_password: (可选)SMTP服务器的认证密码,没提供该参数的情况下,Django会使用EMAIL_HOST_PASSWORD 配置项的设置。
- connection: (可选)发送邮件的后端。没提供该参数的情况下,Django会使用默认后端的实例。可查看 Email backends 了解更多细节。
 
- 创建模板—— - templates/contactForm.html- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24- <html> 
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 <title>Contact us</title>
 </head>
 <body>
 <h1 id="content1">Contact us</h1>
 {% if error %}
 <ul>
 {% for eachError in error %}
 <li> {{eachError}}</li>
 {% endfor %}
 </ul>
 {% endif %}
 <form action="" method="post" accept-charset="utf-8">
 <!-- 此处需要{% csrf_token %}、不然会CSRF验证失败! -->
 <span style="color: #ff0000;">{% csrf_token %}</span>
 <p>Subject: <input type="text" name="subject" value="{{subject}}"></p>
 <p>Your e-mail(optional): <input type="text" name="email" value="{{email}}"></p>
 <p>Message: <textarea name="message" rows="8" cols="40">{{message}}</textarea></p>
 <p><input type="submit" value="Continue →"></p>
 </form>
 </body>
 </html>
- 创建视图函数—— - mysite/views.py- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21- def contact(request): 
 error = []
 if request.method == 'POST':
 if not request.POST.get('subject'):
 error.append('Enter a subject')
 if not request.POST.get('message'):
 error.append('Enter a message')
 if request.POST.get('email') and '@' not in request.POST['email']:
 error.append('Enter a valid email address:')
 if not error:
 emailMessage = ': '.join([request.POST.get('email', 'UserEmailEmpty'), request.POST['message']])
 send_mail(
 request.POST['subject'],
 emailMessage,
 'xxxxx@163.com',
 ['fatesai@gmail.com'],
 fail_silently=True,
 )
 #return HttpResponseRedirect('/contact/thanks/', RequestContext(request))
 return HttpResponseRedirect('/contact/thanks/')
 return render_to_response('contactForm.html', RequestContext(request, {'error': error}))
- URL设置—— - mysite/urls.py- 1 
 2
 3
 4
 5- from mysite.views import contact, thanks 
 urlpatterns = patterns('',
 url(r'^contactus/', contact),
 url(r'^contact/thanks/', thanks)
 )