Why Django?
official website link:
https://www.djangoproject.com/start/overview/
URL
Cool URLs don't change: https://www.w3.org/Provider/Style/URI
urlpatterns = [
url(正则表达式, views视图函数,参数,别名),
]
##参数说明:
一个正则表达式字符串
一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
可选的要传递给视图函数的默认参数(字典形式)
一个可选的name参数
URL无名分组:
urls.py
urlpatterns = [
url('test/(\d+)$', views.test),
]
views.py
def test(request,nid): ####URL中添加无名分组后正则表达式,视图函数中要有参数接收。
return HttpResponse(123)
URL有名分组:
urlpatterns = [
url('manage/(?P<month>\d*)', views.manage),
]
views视图函数中的参数名必须和分组的名称相同。在Python 正则表达式中,命名正则表达式组的语法是(?P<name>pattern),其中name 是组的名称,pattern 是要匹配的模式。
def manage(request,month):
if request.method == 'GET':
print(month)
return HttpResponse(month)
URL分发
#At any point, your urlpatterns can “include” other URLconf modules. This
#essentially “roots” a set of URLs below other ones.
#For example, here’s an excerpt of the URLconf for the Django website itself.
#It includes a number of other URLconfs:
from django.conf.urls import include, url
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^blog/', include('blog.urls')),
]
在blog.urls的文件中,所有的URL都是以blog开头。
URL反向解析
用法一:
urls.py
urlpatterns = [
url('^index/',views.index,name='zss'),
url('^login/',views.login,name='log')
]
views.py
def login(request):
if request.method == 'GET':
print(
111
)
return render(request,'login.html')
else:
print(222)
return HttpResponseRedirect(reverse('zss'))
def index(request):
return render(request,'index.html')
用法二
urls.py
urlpatterns = [
url('^index/',views.index,name='zss'),
url('^login123/',views.login,name='log')
]
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="{% url 'log' %}" method="post"> #####用到别名
{% csrf_token %}
<input type="text">
<input type="password">
<input type="submit" value="提交">
</form>
</body>
</html>
好处:在urls.py 修改url后,不会影响前端的界面url路径,减少后期不必要的繁琐。
名称空间namespace
命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其它命名空间中。
由于name没有作用域,Django在反解URL时,会在项目全局顺序搜索,当查找到第一个name指定URL时,立即返回
我们在开发项目时,会经常使用name属性反解出URL,当不小心在不同的app的urls中定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入了命名空间。
project.urls:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/', include("app01.urls",namespace="app01")),
url(r'^app02/', include("app02.urls",namespace="app02")),
]
app01.urls:
urlpatterns = [
url(r'^index/', index,name="index"),
]
app02.urls:
urlpatterns = [
url(r'^index/', index,name="index"),
]
app01.views
from django.core.urlresolvers import reverse
def index(request):
return HttpResponseRedirect(reverse("app01:index"))
app02.views
from django.core.urlresolvers import reverse
def index(request):
return HttpResponse(reverse("app02:index"))
CBV
cbv(class-base-view) 基于类的视图
fbv(func-base-view) 基于函数的视图
urls.py
urlpatterns = [
url(r'^login.html$', views.Login.as_view()),
views.py
from django.views import View
class Login(View):
def dispatch(self, request, *args, **kwargs):
print('before')
obj = super(Login,self).dispatch(request,*args,**kwargs)
print("after")
return obj
def get(self,request):
return render(request,"login.html")
def post(self,request):
print(request.POST)
return HttpResponse("Login.post")
render函数
render(request, template_name[, context])
结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。
参数:
request: 用于生成响应的请求对象。
template_name:要使用的模板的完整名称,可选的参数
context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。
content_type:生成的文档要使用的MIME类型。默认为DEFAULT_CONTENT_TYPE 设置的值。
status:响应的状态码。默认为200。
redirect 函数
参数可以是:
一个模型:将调用模型的get_absolute_url() 函数
一个视图,可以带有参数:将使用urlresolvers.reverse 来反向解析名称
一个绝对的或相对的URL,将原封不动的作为重定向的位置。
默认返回一个临时的重定向;传递permanent=True 可以返回一个永久的重定向。
模板层(template)
官网:https://docs.djangoproject.com/en/1.10/ref/templates/language/
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
python的模板:HTML代码+模板语法
模版包括在使用时会被值替换掉的 变量,和控制模版逻辑的 标签。
def current_time(req):
# ================================原始的视图函数
# import datetime
# now=datetime.datetime.now()
# html="<html><body>现在时刻:<h1>%s.</h1></body></html>" %now
# ================================django模板修改的视图函数
# from django.template import Template,Context
# now=datetime.datetime.now()
# t=Template('<html><body>现在时刻是:<h1>{{current_date}}</h1></body></html>')
# #t=get_template('current_datetime.html')
# c=Context({'current_date':str(now)})
# html=t.render(c)
#
# return HttpResponse(html)
#另一种写法(推荐)
import datetime
now=datetime.datetime.now()
return render(req, 'current_datetime.html', {'current_date':str(now)[:19]})
模板之过滤器
语法:{{obj|filter__name:param}}
default:
如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。例如:
{{ value|default:"nothing" }}
length
返回值的长度。它对字符串和列表都起作用。例如:
{{ value|length }}
filesizeformat
将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:
{{ value|filesizeformat }}
如果 value 是 123456789,输出将会是 117.7 MB。
date
如果 value=datetime.datetime.now()
{{ value|date:"Y-m-d" }}
slice
如果 value="hello world"
{{ value|slice:"2:-1" }}
truncatechars
如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
参数:要截断的字符数
例如:
{{ value|truncatechars:9 }}
如果value是“Joel 是 a >,输出将为“Joel i ...”
safe
没有管道符safe a标签将在页面上显示‘<a></a>’
模板之标签
for循环
注:循环序号可以通过{{forloop}}显示
forloop.counter The current iteration of the loop (1-indexed)
forloop.counter0 The current iteration of the loop (0-indexed)
forloop.revcounter The number of iterations from the end of the loop (1-indexed)
forloop.revcounter0 The number of iterations from the end of the loop (0-indexed)
forloop.first True if this is the first time through the loop
forloop.last True if this is the last time through the loop
自定义标签和过滤器(simple_tag)
a、在app中创建templatetags模块
b、创建任意 .py 文件,如:xx.py
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)
在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名
{% load xx %}
使用simple_tag
{% my_simple_time 1 2 3%}
{% my_input 'id_username' 'hide'%}
注意:在settings中配置当前app,不然django无法找到自定义的simple_tag
模板继承
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css" />
<title>{% block title %}My amazing site{%/span> endblock %}</title>
</head>
<body>
<div id="sidebar">
{% block sidebar %}
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
{% endblock %}
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
</body>
</html>
这个模版,我们把它叫作 base.html, 它定义了一个可以用于两列排版页面的简单HTML骨架。“子模版”的工作是用它们的内容填充空的blocks。
在这个例子中, block 标签定义了三个可以被子模版内容填充的block。 block 告诉模版引擎: 子模版可能会覆盖掉模版中的这些位置。
子模板看起来是这样的:
{% extends "base.html" %}
{% block title %}My amazing blog{% endblock %}
{% block content %}
{% for entry in blog_entries %}
<h2>{{ entry.title }}</h2>
<p>{{ entry.body }}</p>
{% endfor %}
{% endblock %}
extends 标签是这里的关键。它告诉模版引擎,这个模版“继承”了另一个模版。当模版系统处理这个模版时,首先,它将定位父模版——在此例中,就是“base.html”。
那时,模版引擎将注意到 base.html 中的三个 block 标签,并用子模版中的内容来替换这些block。根据 blog_entries 的值,输出可能看起来是这样的:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css" />
<title>My amazing blog</title>
</head>
<body>
<div id="sidebar">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
</div>
<div id="content">
<h2>Entry one</h2>
<p>This is my first entry.</p>
<h2>Entry two</h2>
<p>This is my second entry.</p>
</div>
</body>
</html>
FBV和CBV
FBV:在URL匹配成功后,会直接执行对应的视图函数
CBV:在URL匹配成功后,会找到视图函数中对应的类,然后再这个类在请求头中找对应的request Method
FBV请求流程
用户发送url请求,Django会依次遍历路由映射表中的所有记录,一旦路由映射表其中的一条匹配成功了,
就执行视图函数中对应的函数名,这是fbv的执行流程
当服务端使用cbv模式的时候,用户发给服务端的请求包含url和method,这两个信息都是字符串类型
CBV请求流程
服务端通过路由映射表匹配成功后会自动去找dispatch方法,然后Django会通过dispatch反射的方式找到类中对应的方法并执行
类中的方法执行完毕之后,会把客户端想要的数据返回给dispatch方法,由dispatch方法把数据返回经客户端