一、路由系统
- 在settings.py文件中通过ROOT_URLCONF指定根级url的配置
- urlpatterns是一个url()实例的列表
- 一个url()对象包括:
- 正则表达式
- 视图函数
- 名称name
- 编写URLconf的注意:
- 若要从url中捕获一个值,需要在它周围设置一对圆括号
- 不需要添加一个前导的反斜杠,如应该写作'test/',而不应该写作'/test/'
- 每个正则表达式前面的r表示字符串不转义
- 请求的url被看做是一个普通的python字符串,进行匹配时不包括get或post请求的参数及域名
http://www.itcast.cn/python/1/?i=1&p=new,只匹配“/python/1/”部分
1、单一路由对应
url(r'^index$', views.index),
2、基于正则的路由
url(r'^index/(d*)', views.index), url(r'^manage/(?P<name>w*)/(?P<id>d*)', views.manage),
3、添加额外的参数
url(r'^manage/(?P<name>w*)', views.manage,{'id':333}),
4、为路由映射设置名称
url(r'^home', views.home, name='h1'), url(r'^index/(d*)', views.index, name='h2'),
设置名称之后,可以在不同的地方调用
URL的反向解析
- 如果在视图、模板中使用硬编码的链接,在urlconf发生改变时,维护是一件非常麻烦的事情
- 解决:在做链接时,通过指向urlconf的名称,动态生成链接地址视图:使用from django.urls import reverse函数
- 模板中使用生成URL {% url 'h2' 2012 %}
<a href="{% url 'h2' 2012 %}">link</a> 渲染出来的就是 <a href="/h2/2012/">link</a>
- Model中使用获取URL 自定义get_absolute_url() 方法
class NewType(models.Model): caption = models.CharField(max_length=16) def get_absolute_url(self): """ 为每个对象生成一个URL 应用:在对象列表中生成查看详细的URL,使用此方法即可!!! :return: """ # return '/%s/%s' % (self._meta.db_table, self.id) # 或 from django.urls import reverse return reverse('NewType.Detail', kwargs={'nid': self.id})
获取请求匹配成功的URL信息:request.resolver_match
- 函数中使用生成URL reverse('h2', args=(2012,)) 路径:django.urls.reverse
另外,比如用户收藏夹中收藏的URL是旧的,如何让以前的 /h2/2012/自动跳转到现在新的网址呢?
要知道Django不会帮你做这个,这个需要自己来写一个跳转方法:
具体思路是,在 views.py 写一个跳转的函数:
from django.http import HttpResponseRedirect from django.core.urlresolvers import reverse # Django 1.4.x - Django 1.10.x # from django.urls import reverse # Django 1.10.x - Django 2.x def old_h2_redirect(request, a): return HttpResponseRedirect( reverse('h2', args=(a, )) )
url.py中:
url(r'^old_h2/(d+)/$', views.old_h2_redirect), url(r'^h2/(d+)/$', views.h2, name='h2'),
5、根据app对路由规则进行分类
url(r'^web/',include('web.urls')),
6、命名空间
a. project.urls.py
from django.conf.urls import url,include urlpatterns = [ url(r'^a/', include('app01.urls', namespace='author-polls')), url(r'^b/', include('app01.urls', namespace='publisher-polls')), ]
b. app01.urls.py
from django.conf.urls import url from app01 import views app_name = 'app01' urlpatterns = [ url(r'^(?P<pk>d+)/$', views.detail, name='detail') ]
c. app01.views.py
def detail(request, pk): print(request.resolver_match) return HttpResponse(pk)
以上定义带命名空间的url之后,使用name生成URL时候,应该如下:
- v = reverse('app01:detail', kwargs={'pk':11})
- {% url 'app01:detail' pk=12 %}
django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。
二、模板
1、模版的执行
模版的创建过程,对于模版,其实就是读取模版(其中嵌套着模版标签),然后将 Model 中获取的数据插入到模版中,最后将信息返回给用户。
def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
from django import template t = template.Template('My name is {{ name }}.') c = template.Context({'name': 'Adrian'}) print t.render(c)
import datetime from django import template import DjangoDemo.settings now = datetime.datetime.now() fp = open(settings.BASE_DIR+'/templates/Home/Index.html') t = template.Template(fp.read()) fp.close() html = t.render(template.Context({'current_date': now})) return HttpResponse(html)
from django.template.loader import get_template from django.template import Context from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() t = get_template('current_datetime.html') html = t.render(Context({'current_date': now})) return HttpResponse(html)
return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))
from django.shortcuts import render import datetime def index(request): now = datetime.datetime.now() return render(request, 'index.html', {'current_time':now})
2、模版语言
模板中也有自己的语言,该语言可以实现数据展示
1 列表,字典,类的实例的使用 2 3 循环:迭代显示列表,字典等中的内容 4 5 条件判断:判断是否显示该内容,比如判断是手机访问,还是电脑访问,给出不一样的代码。 6 7 标签:for,if 这样的功能都是标签。 8 9 过滤器:管道符号后面的功能,比如{{ var|length }},求变量长度的 length 就是一个过滤器。
a、一般的变量之类的用 {{ }}(变量)
- {{ item }}
b、循环:迭代显示列表,字典等中的内容
- {% for item in item_list %} <a>{{ item }}</a> {% endfor %}
for 循环要有一个结束标记
- 在for循环中还有很多有用的东西,如下:
变量 | 描述 |
---|---|
forloop.counter | 索引从 1 开始算 |
forloop.counter0 | 索引从 0 开始算 |
forloop.revcounter | 索引从最大长度到 1 |
forloop.revcounter0 | 索引从最大长度到 0 |
forloop.first | 当遍历的元素为第一项时为真 |
forloop.last | 当遍历的元素为最后一项时为真 |
forloop.parentloop |
用在嵌套的 for 循环中,获取上一层 for 循环的 forloop |
- 当列表中可能为空值时用 for empty
<ul> {% for athlete in athlete_list %} <li>{{ athlete.name }}</li> {% empty %} <li>抱歉,列表为空</li> {% endfor %} </ul>
d、判断 {% if ordered_warranty %} {% else %} {% endif %}
e、网站模板的设计,一般的,我们做网站有一些通用的部分,比如 导航,底部,访问统计代码等等
- 可以写一个 base.html 来包含这些通用文件(include)
-
母板:{% block title %}{% endblock %}
子板:{% extends "base.html" %}
{% block title %}{% endblock %}
-
<!DOCTYPE html> <html> <head> <title>{% block title %}默认标题{% endblock %} - 标题</title> </head> <body> {% include 'nav.html' %} <div>include 是包含其它文件的内容</div> {% block content %} <div>这里是默认内容,所有继承自这个模板的,如果不覆盖就显示这里的默认内容。</div> {% endblock %} {% include 'bottom.html' %} {% include 'tongji.html' %} </body> </html>
如果需要,写足够多的 block 以便继承的模板可以重写该部分,include 是包含其它文件的内容,就是把一些网页共用的部分拿出来,重复利用,改动的时候也方便一些,还可以把广告代码放在一个单独的html中,改动也方便一些,在用到的地方include进去。其它的页面继承自 base.html 就好了,继承后的模板也可以在 block 块中 include 其它的模板文件。
比如我们的首页 home.html,继承或者说扩展(extends)原来的 base.html,可以简单这样写,重写部分代码(默认值的那一部分不用改)
{% extends 'base.html' %} {% block title %}欢迎光临首页{% endblock %} {% block content %} {% include 'ad.html' %} 这里是首页,欢迎光临 {% endblock %}
f、模板上得到视图对应的网址:
# views.py def add(request, a, b): c = int(a) + int(b) return HttpResponse(str(c)) # urls.py urlpatterns = patterns('', url(r'^add/(d+)/(d+)/$', 'app.views.add', name='add'), ) # template html {% url 'add' 4 5 %}
这样网址上就会显示出:/add/4/5/ 这个网址,假如我们以后修改 urls.py 中的
r'^add/(d+)/(d+)/$'
这一部分,改成另的,比如:
r'^jiafa/(d+)/(d+)/$'
这样,我们不需要再次修改模板,当再次访问的时候,网址会自动变成 /jiafa/4/5/
还可以使用 as 语句将内容取别名(相当于定义一个变量),多次使用(但视图名称到网址转换只进行了一次)
{% url 'some-url-name' arg arg2 as the_url %} <a href="{{ the_url }}">链接到:{{ the_url }}</a>
g、 ==, !=, >=, <=, >, < 这些比较都可以在模板中使用;and, or, not, in, not in 也可以在模板中使用
h、模板中 获取当前网址,当前用户等:
- 获取当前用户:
{{ request.user }}
如果登陆就显示内容,不登陆就不显示内容:
{% if request.user.is_authenticated %} {{ request.user.username }},您好! {% else %} 请登陆,这里放登陆链接 {% endif %}
- 获取当前网址:
{{ request.path }}
- 获取当前 GET 参数
{{ request.GET.urlencode }}
- 合并到一起用的一个例子:
<a href="{{ request.path }}?{{ request.GET.urlencode}}&delete=1">当前网址加参数 delete</a>
比如我们可以判断 delete 参数是不是 1 来删除当前的页面内容。
i、帮助方法:
{{ item.event_start|date:"Y-m-d H:i:s"}}
{{ bio|truncatewords:"30" }}
{{ my_list|first|upper }}
{{ name|lower }}
3、自定义simple_tag
a、在app中创建templatetags模块
b、创建任意 .py 文件,如:xx.py
#!/usr/bin/env python #coding:utf-8 from django import template from django.utils.safestring import mark_safe register = template.Library() @register.simple_tag def my_simple_time(v1,v2,v3): return v1 + v2 + v3 @register.simple_tag def my_input(id,arg): result = "<input type='text' id='%s' class='%s' />" %(id,arg,) return mark_safe(result)
c、在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名
{% load xx %}
d、使用simple_tag
{% my_simple_time 1 2 3%} {% my_input 'id_username' 'hide'%}
e、在settings中配置当前app,不然django无法找到自定义的simple_tag