Python 框架之 Django (进阶)

URLconf 配置

示例一

Python

1urlpatterns = patterns('',
2    (r'^hello/$', 'mysite.views.hello'),
3    (r'^time/$', 'mysite.views.current_datetime'),
4    (r'^time/plus/(\d{1,2})/$', 'mysite.views.hours_ahead'),
5    (r'^tag/(\w+)/$', 'weblog.views.tag'),
6)

示例二

Python

1urlpatterns = patterns('mysite.views',
2    (r'^hello/$', 'hello'),
3    (r'^time/$', 'current_datetime'),
4    (r'^time/plus/(\d{1,2})/$', 'hours_ahead'),
5)
6 
7urlpatterns += patterns('weblog.views',
8    (r'^tag/(\w+)/$', 'tag'),
9)

示例三

Python

1urlpatterns = patterns('',
2    (r'^articles/(?P\d{4})/$', views.year_archive),
3    (r'^articles/(?P\d{4})/(?P\d{2})/$', views.month_archive),
4)
5if settings.DEBUG:
6    urlpatterns += patterns('',
7        (r'^debuginfo/$', views.debug),
8    )

示例四

Python

1urlpatterns = patterns('',
2    (r'^foo/$', views.foobar_view, {'template_name': 'template1.html'}),
3    (r'^bar/$', views.foobar_view, {'template_name': 'template2.html'}),
4)

示例五

Python

1urlpatterns = patterns('',
2    (r'^mydata/birthday/$', views.my_view, {'month': 'jan', 'day': '06'}),
3    (r'^mydata/(?P\w{3})/(?P\d\d)/$', views.my_view),
4)

示例六 请求分支

Python

1def some_page(request):
2    if request.method == 'POST':
3        do_something_for_post()
4        return HttpResponseRedirect('/someurl/')
5    elif request.method == 'GET':
6        do_something_for_get()
7        return render_to_response('page.html')
8    else:
9        raise Http404()

Python

01from django.http import Http404, HttpResponseRedirect
02from django.shortcuts import render_to_response
03 
04def method_splitter(request, GET=None, POST=None):
05    if request.method == 'GET' and GET is not None:
06        return GET(request)
07    elif request.method == 'POST' and POST is not None:
08        return POST(request)
09    raise Http404
10 
11def some_page_get(request):
12    assert request.method == 'GET'
13    do_something_for_get()
14    return render_to_response('page.html')
15 
16def some_page_post(request):
17    assert request.method == 'POST'
18    do_something_for_post()
19    return HttpResponseRedirect('/someurl/')
20 
21# urls.py
22 
23from django.conf.urls.defaults import *
24from mysite import views
25 
26urlpatterns = patterns('',
27    # ...
28    (r'^somepage/$', views.method_splitter, {'GET': views.some_page_get, 'POST': views.some_page_post}),
29    # ...
30)

示例七

Python

01def my_view1(request):
02    if not request.user.is_authenticated():
03        return HttpResponseRedirect('/accounts/login/')
04    return render_to_response('template1.html')
05def my_view2(request):
06    if not request.user.is_authenticated():
07        return HttpResponseRedirect('/accounts/login/')
08    return render_to_response('template2.html')
09def my_view3(request):
10    if not request.user.is_authenticated():
11        return HttpResponseRedirect('/accounts/login/')
12    return render_to_response('template3.html')
13def requires_login(view):
14    def new_view(request, *args, **kwargs):
15        if not request.user.is_authenticated():
16            return HttpResponseRedirect('/accounts/login/')
17        return view(request, *args, **kwargs)
18    return new_view
19--------------------------
20urlpatterns = patterns('',
21    (r'^view1/$', requires_login(my_view1)),
22    (r'^view2/$', requires_login(my_view2)),
23    (r'^view3/$', requires_login(my_view3)),
24)

示例八:include()
被捕获的 username 变量将传递给被包含的 URLconf,进而传递给那个URLconf中的 每一个 视图函数。

Python

01from django.conf.urls.defaults import *
02urlpatterns = patterns('',
03    (r'^(?P\w+)/blog/', include('foo.urls.blog') ,{'blogid': 3}), #包含进foo.urls.blog中,但不会马上执行
04)
05# foo/urls/blog.py
06from django.conf.urls.defaults import *
07urlpatterns = patterns('',
08    (r'^$', 'foo.views.blog_index'),
09    (r'^archive/$', 'foo.views.blog_archive'),
10)

模板

django.template.RequestContext

RequestContext 默认地在模板context中加入了一些变量,如 HttpRequest 对象或当前登录用户的相关信息。 当你不想在一系例模板中都明确指定一些相同的变量时,你应该使用 RequestContext

全局模板变量

不论它们存放在哪个物理路径下,只要在你的Python搜索路径中,你就可以在 TEMPLATE_CONTEXT_PROCESSORS 设置里指向它们。 建议你把它们放在应用或者工程目录下名为 context_processors.py 的文件里。

默认的

Python

1TEMPLATE_CONTEXT_PROCESSORS = (
2    'django.core.context_processors.auth',
3    'django.core.context_processors.debug',
4    'django.core.context_processors.i18n',
5    'django.core.context_processors.media',
6)

可添加 django.core.context_processors.request

custom_proc: TEMPLATE_CONTEXT_PROCESSORS = (mysite.下面的文件名.custom_proc)

Python

01from django.shortcuts import render_to_response
02from django.template import RequestContext
03 
04def custom_proc(request):
05    "A context processor that provides 'app', 'user' and 'ip_address'."
06    return {
07        'app': 'My app',
08        'user': request.user,
09        'ip_address': request.META['REMOTE_ADDR']
10    }
11 
12def view_1(request):
13    # ...
14    return render_to_response('template1.html',
15        {'message': 'I am view 1.'},
16        context_instance=RequestContext(request, processors=[custom_proc]))
17 
18def view_2(request):
19    # ...
20    return render_to_response('template2.html',
21        {'message': 'I am the second view.'},
22        context_instance=RequestContext(request, processors=[custom_proc]))

关闭模板自动转意: {{ data|safe }}
{% autoescape off %}
Hello {{ name }}
{% endautoescape %}
auto-escaping 标签的作用域不仅可以影响到当前模板还可以通过include标签作用到其他标签,就像block标签一样。
过滤器参数里的字符串常量的自动转义:{{ data|default:"3 < 2" }}
扩展模板系统:http://djangobook.py3k.cn/2.0/chapter09/

数据模型

http://djangobook.py3k.cn/2.0/chapter10/

访问外键(Foreign Key)值

Python

1from mysite.apptest.models import Book
2b = Book.objects.get(id=50)
3print(b.publisher)
4p = Publisher.objects.get(name='Apress1')
5print(p.book_set.all()) #book_set 只是一个 QuerySet,所以它可以像QuerySet一样,能实现数据过滤和分切

访问多对多值(Many-to-Many Values)
多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例

Python

1b = Book.objects.get(id=1)
2b.authors.all()

增加额外的Manager方法 我们为Book模型定义了一个title_count()方法

Python

1class BookManager(models.Manager):
2    def title_count(self, keyword):
3        return self.filter(title__icontains=keyword).count()

Python

1class Book(models.Model):
2    title = models.CharField(max_length=100)
3    authors = models.ManyToManyField(Author)
4    publisher = models.ForeignKey(Publisher)
5    publication_date = models.DateField()
6    objects = BookManager()
7    def __unicode__(self):
8        return self.title

模型方法与属性执行原始SQL查询
connection和cursor几乎实现了标准Python DB-API

Python

1>>> from django.db import connection
2>>> cursor = connection.cursor()
3>>> cursor.execute("""
4...    SELECT DISTINCT first_name
5...    FROM people_person
6...    WHERE last_name = %s""", ['Lennon'])
7>>> row = cursor.fetchone()
8>>> print row

通用视图

呈现静态“关于”页面的URLconf

Python

1]
2from django.conf.urls.defaults import *
3from django.views.generic.simple import direct_to_template
4 
5urlpatterns = patterns('',
6    (r'^about/$', direct_to_template, {'template': 'about.html'})
7    (r'^about/(\w+)/$', about_pages),
8)

对象的通用视图

Python

01from django.conf.urls.defaults import *
02from django.views.generic import list_detail
03from apptest.apptest.models import Publisher
04def get_books():
05    return Book.objects.all()
06 
07publisher_info = {
08    'queryset': Publisher.objects.all(),
09    'template_name': 'publisher_list_page.html',#缺省的情况是"books/publisher_list.html"
10    'template_object_name': 'publisher', #缺省的情况是 object_list
11    #'extra_context': {'book_list': Book.objects.all()} #添加额外的Context,objects.all() 在URLconf中,只会执行一次,后面的添删不影响boo_list
12    extra_context': {'book_list': get_books} #任何传递给extra_context的可调用对象(例如一个函数)都会在每次视图渲染前执行(而不是只执行一次)
13    #extra_context': {'book_list': Book.objects.all} #或者使用Book.objects.all函数做参数,而不是它的执行结果做参数
14 
15}
16 
17urlpatterns = patterns('',
18    (r'^publishers/$', list_detail.object_list, publisher_info)
19)

扩展通用视图
用函数包装来处理复杂的数据过滤

Python

01from django.shortcuts import get_object_or_404
02from django.views.generic import list_detail
03from mysite.apptest.models import Book, Publisher
04def books_by_publisher(request, name):
05    # Look up the publisher (and raise a 404 if it can't be found).
06    publisher = get_object_or_404(Publisher, name__iexact=name)
07 
08    # Use the object_list view for the heavy lifting.
09    return list_detail.object_list(
10        request,
11        queryset = Book.objects.filter(publisher=publisher),
12        template_name = 'books/books_by_publisher.html',
13        template_object_name = 'book',
14        extra_context = {'publisher': publisher}
15    )

处理额外工作
修改视图返回值

Python

01def author_detail(request, author_id):
02    # Delegate to the generic view and get an HttpResponse.
03    response = list_detail.object_detail(
04        request,
05        queryset = Author.objects.all(),
06        object_id = author_id,
07    )
08    now = datetime.datetime.now()
09    Author.objects.filter(id=author_id).update(last_accessed=now)
10    return response

文件下载:Content-Disposition 的含义是 告诉浏览器下载并保存这个页面

Python

1def author_list_plaintext(request):
2    response = list_detail.object_list(
3        request,
4        queryset = Author.objects.all(),
5        mimetype = 'text/plain',
6        template_name = 'books/author_list.txt'
7    )
8    response["Content-Disposition"] = "attachment; filename=authors.txt"
9    return response

输出非HTML内容

视图和MIME类型

Python

1from django.http import HttpResponse
2 
3def my_image(request):
4    image_data = open("/path/to/my/image.png", "rb").read()
5    return HttpResponse(image_data, mimetype="image/png")

生成 CSV 文件
响应返回的是 text/csv MIME类型(而非默认的 text/html )。这会告诉浏览器,返回的文档是CSV文件。

Python

01import csv
02from django.http import HttpResponse
03 
04# Number of unruly passengers each year 1995 - 2005. In a real application
05# this would likely come from a database or some other back-end data store.
06UNRULY_PASSENGERS = [146,184,235,200,226,251,299,273,281,304,203]
07 
08def unruly_passengers_csv(request):
09    # Create the HttpResponse object with the appropriate CSV header.
10    response = HttpResponse(mimetype='text/csv')
11    response['Content-Disposition'] = 'attachment; filename=unruly.csv'
12 
13    # Create the CSV writer using the HttpResponse as the "file."
14    writer = csv.writer(response)
15    writer.writerow(['Year', 'Unruly Airline Passengers'])
16    for (year, num) in zip(range(1995, 2006), UNRULY_PASSENGERS):
17        writer.writerow([year, num])
18 
19    return response

生成 PDF 文件 安装 ReportLab: http://www.reportlab.org/downloads.html.

Python

01from reportlab.pdfgen import canvas
02from django.http import HttpResponse
03 
04def hello_pdf(request):
05    # Create the HttpResponse object with the appropriate PDF headers.
06    response = HttpResponse(mimetype='application/pdf')
07    response['Content-Disposition'] = 'attachment; filename=hello.pdf'
08 
09    # Create the PDF object, using the response object as its "file."
10    p = canvas.Canvas(response)
11 
12    # Draw things on the PDF. Here's where the PDF generation happens.
13    # See the ReportLab documentation for the full list of functionality.
14    p.drawString(100, 100, "Hello world.")
15 
16    # Close the PDF object cleanly, and we're done.
17    p.showPage()
18    p.save()
19    return response
需要注意以下几点:

这里我们使用的 MIME 类型是 application/pdf 。这会告诉浏览器这个文档是一个 PDF 文档,而不是 HTML 文档。 如果忽略了这个参数,浏览器可能会把这个文件看成 HTML 文档,这会使浏览器的窗口中出现很奇怪的文字。 If you leave off this information, browsers will probably interpret the response as HTML, which will result in scary gobbledygook in the browser window.

使用 ReportLab 的 API 很简单: 只需要将 response 对象作为 canvas.Canvas 的第一个参数传入。

所有后续的 PDF 生成方法需要由 PDF 对象调用(在本例中是 p ),而不是 response 对象。

最后需要对 PDF 文件调用 showPage() 和 save() 方法(否则你会得到一个损坏的 PDF 文件)。

复杂的 PDF 文件
如果您在创建一个复杂的 PDF 文档(或者任何较大的数据块),请使用 cStringIO 库存放临时生成的 PDF 文件。 cStringIO 提供了一个用 C 编写的类似文件对象的接口,从而可以使系统的效率最高。 下面是使用 cStringIO 重写的 Hello World 例子

Python

01from cStringIO import StringIO
02from reportlab.pdfgen import canvas
03from django.http import HttpResponse
04 
05def hello_pdf(request):
06    # Create the HttpResponse object with the appropriate PDF headers.
07    response = HttpResponse(mimetype='application/pdf')
08    response['Content-Disposition'] = 'attachment; filename=hello.pdf'
09 
10    temp = StringIO()
11 
12    # Create the PDF object, using the StringIO object as its "file."
13    p = canvas.Canvas(temp)
14 
15    # Draw things on the PDF. Here's where the PDF generation happens.
16    # See the ReportLab documentation for the full list of functionality.
17    p.drawString(100, 100, "Hello world.")
18 
19    # Close the PDF object cleanly.
20    p.showPage()
21    p.save()
22 
23    # Get the value of the StringIO buffer and write it to the response.
24    response.write(temp.getvalue())
25    return response

其它文件类型

ZIP 文件 :Python 标准库中包含有 zipfile 模块,它可以读和写压缩的 ZIP 文件。 它可以用于按需生成一些文件的压缩包,或者在需要时压缩大的文档。
动态图片 : Python 图片处理库 (PIL; http://www.pythonware.com/products/pil/) 是极好的生成图片(PNG, JPEG, GIF 以及其它许多格式)的工具。 它可以用于自动为图片生成缩略图,将多张图片压缩到单独的框架中,或者是做基于 Web 的图片处理。
图表 :matplotlib (http://matplotlib.sourceforge.net/) 可以用于生成通常是由 matlab 或者 Mathematica 生成的高质量图表。
pygraphviz (https://networkx.lanl.gov/wiki/pygraphviz) 是一个 Graphviz 图形布局的工具 (http://graphviz.org/) 的 Python 接口,可以用于生成结构化的图表和网络。

内容聚合器应用框架

RSS和Atom都是基于XML的格式,你可以用它来提供有关你站点内容的自动更新的feed

http://djangobook.py3k.cn/2.0/chapter13/

会话、用户和注册

Cookies

Python

1def show_color(request):
2    request.COOKIES["favorite_color"]
3    response.set_cookie("favorite_color",request.GET["favorite_color"])

可选的参数: 参数, 缺省值, 描述
max_age, None, cookie需要延续的时间(以秒为单位)cookie将持续,直到浏览器关闭。
expires, None, cookie失效的实际日期/时间,格式 "Wdy, DD-Mth-YY HH:MM:SS GMT" 此参数将覆盖max_age参数。
path, /, cookie, 生效的路径,特别用天当你无法控制网站的顶级域名。
domain, None, cookie有效的域名, 例 domain=".example.com" 指 *.example.com
secure, false, 如果设置为True, 则指定使用 https 的方式来访问这个cookie
设置测试Cookies: request.session.set_test_cookie(),test_cookie_worked(),delete_test_cookie()

Sessions

Sessions在Django中是一个字典型的对象:如 keys() 和 items() 对 request.session 同样有效
Session字典中以下划线开头的key值是Django内部保留key值。
不要用一个新对象来替换掉 request.session ,也不要存取其属性。

打开sessions功能

编辑 MIDDLEWARE_CLASSES 配置,确保 MIDDLEWARE_CLASSES 中包含 'django.contrib.sessions.middleware.SessionMiddleware'。
确认 INSTALLED_APPS 中有 'django.contrib.sessions' (如果你是刚打开这个应用,别忘了运行 manage.py syncdb )

在视图中使用Session

Python

1request.session["fav_color"] = "blue"
2fav_color = request.session["fav_color"]
3del request.session["fav_color"]
4if "fav_color" in request.session:
5    ......

在视图(View)外使用Session:使用Django数据库API来存取session

Python

1from django.contrib.sessions.models import Session
2s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
3print(s.expire_date)

你需要使用get_decoded() 来读取实际的session数据。 这是必需的,因为字典存储为一种特定的编码格式。

Python

1>>> s.session_data
2'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
3>>> s.get_decoded()
4{'user_id': 42}

何时会自动保存Session:session_data字典赋值或删除
浏览器关闭即失效会话 vs 持久会话

改变 SESSION_EXPIRE_AT_BROWSER_CLOSE 的设置来控制session自动过期
缺省情况下, SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为 False ,这样,会话cookie可以在用户浏览器中保持有效达 SESSION_COOKIE_AGE 秒(缺省设置是两周,即1,209,600 秒)
如果 SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为 True ,当浏览器关闭时,Django会使cookie失效。

其他的Session设置

SESSION_COOKIE_DOMAIN, 使用会话cookie(session cookies)的站点。 将它设成一个字符串,就好象`` “.example.com”`` 以用于跨站点(cross-domain)的cookie,或`` None`` 以用于单个站点。
SESSION_COOKIE_NAME, 会话中使用的cookie的名字。 它可以是任意的字符串。	如:"sessionid"
SESSION_COOKIE_SECURE, 是否在session中使用安全cookie。 如果设置 True , cookie就会标记为安全, 这意味着cookie只会通过HTTPS来传输。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值