最近在整理之前的笔记,这是之前自学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.py
1
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
8from 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
4from 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
中添加URLconf1
2
3
4
5from 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
17import 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
4urlpatterns = 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.py
1
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.py
1
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
6from 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
4from 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
4from 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
12from 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
5from 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
21def 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
5from mysite.views import contact, thanks
urlpatterns = patterns('',
url(r'^contactus/', contact),
url(r'^contact/thanks/', thanks)
)