小生博客:http://xsboke.blog.51cto.com

                            -------谢谢您的参考,如有疑问,欢迎交流

一、静态文件 二、路由映射 三、视图函数 四、template(模板)基础

  1. 关于静态文件

    1.1 首先需要在配置文件settings.py中指定静态目录 STATICFILES_DIRS = ( os.path.join(BASE_DIR,"statics"), )

    1.2 然后在html中使用django模板语言指定静态文件 {% load static from staticfiles %} <link href="{% static "index.css" %}" rel="stylesheet" type="text/css" /> <script src="{% static "index.js" %} "></script>

    1.3 也可以这样写

     # 指定前缀
     STATIC_URL = '/a/' 
     
     STATICFILES_DIRS = (
     os.path.join(BASE_DIR,"statics"),
     )
     
     
     <link href="/a/css/index.css" rel="stylesheet" type="text/css" />
     <script src="/a/js/index.js"></script>
    
  2. 路由映射

    Django URL是一个URL和视图函数的映射表

    urlpatterns = [ path('admin/', admin.site.urls), ]

    urlpatterns = [ url(正则表达式,views视图函数,参数,别名) ] 参数:可选的要传递给视图函数的默认参数 别名:一个可选的name参数,用于前端

    注意:要想使用url去配置路径需要加载模块:from django.conf.urls import url

    2.1 无名分组 url(r'^articles/[0-9]{4}/([0-9]{4})/([0-9]+)/$',views.special_case_2018), ^articles:以articles开头匹配articles /:目录符号 [0-9]{4}:包含一个4位数,每一位的范围是0-9 ():加括号的意思是传入一个参数 这时候,views.py需要这样写(使用HttpResponsen需要导入这个模块): def special_case_2018(req,变量) #可以传入多个变量,用逗号分隔 return HttpResposen(变量+"year") #将用户输入的内容返回到浏览器上

    2.2 命名分组

    2.2.1 讲解 import re

     ret = re.search('(?P<id>\d{3})/(?P<name>\w{3})','weeew34ttt123/ooo')
     
     ?P:固定格式,意思是这种分组是有名字的
     <id>:匹配的名字就是id,可以看做是一个变量,是匹配内容的变量
     \d{3}:是匹配的内容,3个数字。
     \w{3}:就是3个字母
     'weeew34ttt123/ooo':这段字符串就是被匹配的内容,最终结果会匹配出"123/ooo"
     
     
     print(ret.group())		:取出所有匹配到的内容
     print(ret.group('id'))	:只取出名字为的id的内容
     print(ret.group('name')):只取出名字为的name的内容
    

    2.2.2 url格式 urlpatterns = [ url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{4})/$',views.year_archive), ]

     views.py配置
     def year_archive(req,year,month):				# 使用命名分组,形参必须是url中定义的名字,顺序可以不同
     	return HttpResposen(year+"y"+month+"m")
    

    2.3 参数三 urlpatterns = [ url(r'index',views.index,{"name":'dashan'}), ]

     def index(req,name):
     	return HttpResposen(name)		# 返回"dashan"
     	# 如果在使用参数的同时,使用了命名分组,两边的名字如果一样,那么参数会覆盖命名分组
    

    2.4 参数四 urlpatterns = [ url(r'index',views.index,name="dashan"), # name是固定的写法,name就是别名 ] # name="dashang",代替的就是index,就是index的别名

     这时候,前端可以通过别名去找到视图函数
     
     <form action={% url "dashan" %} method="post">
     	<input type="text" name="usernmae">
     	<input type="passwrod" name="passwd">
     	<input type="submit" name="submit">
     <form>
    

    2.5 url映射分发(include) 当有上万页面时,你就得在urls.py中写上万条url匹配,造成数据量大,容易写重,容易造成结藕

     解决方法:在每个app下创建一个urls.py,全局的urls.py只做一个映射
     
     2.5.1 全局urls.py
     
     	from django.conf.urls import url,include
     	from appname import views
     
     	urlpatterns = [
     		url(r'^appname',include('appname.urls')),
     	]
     	
     2.5.2 app的urls.py
     	from django.conf.urls import url,include
     	
     	urlpatterns = [
     		url(r'page1/page1.1',views.page1),   	# page1是紧跟appname的内容
     		url(r'page2',views.page2),
     	]
    
  3. 视图函数

    HTTP请求中产生两个核心对象: http请求:HttpRequest对象 http响应:HttpResponse对象 所在位置:django.http

     # 获取两种请求方法
     request.POST.get
     request.GET.get
    

    3.1 HttpRequest对象的属性 path: 请求页面的全路径,不包括域名 method: 请求中使用的HTTP方法的字符串表示,全大写表示。例如GET和POST if req.method == "POST" or req.method == "GET" GET: 包含所有HTTP GET参数的类字典对象 POST: 包含所有HTTP POST参数的类字典对象 服务器收到空的POST请求的情况也是可能发生的,也就是说,表单form通过 HTTP POST方法提交请求,但是表单中可能没有数据,因此不能使用 if req.POST 来判断是否使用的HTTP POST 方法,应该使用 if req.method == "POST"

     COOKIES:	包含所有cookies的标准python字典对象;key和values都是字符串
     FILE:		包含所有上传文件的类字典对象;files中的米一个key都是<input type="file" name="" />标签中
     			name的属性值,files中的每一个values同时也是一个标准的python字典对象,包含下面是哪个keys:
     				
     				filename:		上传文件名,用字符串表示
     				content_type:	上传文件的Content Type
     				content:		上传文件的原始内容
     user:		是一个Django.contrib.auth.models.User对象,代表当前登录的用户,如果访问用户当前没有登录,
     			user将初始化为django.contrib.auth.models.AnonymousUser的实例。你可以通过user的
     			is_authenticated()方法来辨别用户是否登录:
     				if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware时,该属性
     				才可用
     				
     session:	唯一可读写的属性,代表当前会话的字典对象;只有激活Django中的session支持时该属性才可用
    

    3.2 HttpResponse对象 对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建, 每个view请求处理方法必须返回一个HttpResponse对象。

     HttpResponse类在django.http.HttpResponse
     在HttpResponse对象上扩展的常用方法:
     	页面渲染: render(),render_to_response(),  
     		# 使用render_to_response()方法需要引入render_to_response模块
     			return render(req,"index.html")
     			return render_to_response("index.html")			-- 有坑不建议使用
     	
     	
     	
     	本地变量:locals():	可以直接将函数中所有的变量传给模板,locals是本地变量的意思,将本地变量传入html中
     		例:
     			views.py 中写
     				name="dashan"
     				return render_to_response("index.html",{"a":name})	
     			html就得写
     				{{ a }}
     				
     				
     			当views.py 这样写
     				name="dashan"
     				return render_to_response("index.html",locals())
     				
     			html就可以这样写,直接调用变量,而不需要使用参数调用
     				{{ name }}
     				
     			注意,使用render也可以
     		
     	
     	页面跳转(重定向): redirect()
     		return redirect("http://www.baidu.com")
     		return redirect("http://www.baidu.com")
     		
     		
     		render 是直接渲染某个页面并返回,redirect是重定向到指定的views函数,同时也会做一定的判断,
     		比如用户登录。
    
  4. template基础

    在向前端输出字符串时使用模板语言进行处理,而不是使用 "欢迎 %s 登录" %(name) ,这种方式是为了实现前后端分离

    什么是模板语言? 格式:HTML + 逻辑控制语句,如果HTML中存在模板语言,则HTML就叫模板,而不是HTML

    模板语言的作用? 起到前端到后端的纽带作用

     render(request,"index.html",{"name":name})
     	"index.html"		就叫模板
     	{"name":name}		就叫上下文,Context
     	
     	
     在pycharm的terminal界面输入python manage.py shell即可进入当前django的命令行
     输入:
     >>>	t=Template("hello {{ name }}")			创建模板语言
     >>>	c=Context({"name":"dashan"})			创建上下文
     >>>	t.render(c)								渲染模板语言和上下文
     'hello dashan'
    

    4.1 一次模板创建,多次调用render()实现更高效的渲染

     t = Template("hello, {{ name }}")
     for name in ('dashan','lisi','wangwu'):
     	print t.render(Context({'name'}:name))
     	
     
     在view中使用Template和Context需要引入,from django.template import Template,Context
    

    4.2 深度变量的查找(万能的句点号".")

     import datetime
     
     def index(req):
     	s=[1,2,3,4]
     	s2={"uname":"dashan","sex":23}
     	s3=datetime.datetime.now()
     	
     	class Person:
     		def __init__(self,name,age):
     			self.name = name
     			self.age = age
     			
     	s4=Person("dashan",18)
     	
     	return render(req,"index.html",{"list":s})
     	return render(req,"index.html",{"obj":s2})
     	return render(req,"index.html",{"time":s3})
     	return render(req,"index.html",{"P":s4})
     	
     	
     <html>
     	<p> Template </p>
     	{{ list.2}}   <!-- 输出的结果是3 ,列表通过索引取值-->
     	{{ obj.sex}}   <!-- 输出的结果是23,字典通过key取values -->
     	{{ time.year }}   <!-- 属性也是通过"."召唤出来的 -->
     	{{ time.month }}   <!-- 属性也是通过"."召唤出来的 -->
     	{{ P.age }}   <!-- 属性也是通过"."召唤出来的,结果是18 -->
     	{{ P }}   <!-- 如果不加属性,那么输出的是一个对象属性 -->
     </html>
    

    4.3 if和for循环

     4.3.1 if,只支持布尔值True或者False,1(True)和(False)也可以
     
     	{ % if True % }
     		<p>hello world</p>
     		{ % elif obj % }
     			<p>hello2</p>
     	{ % endif % }
     	
     4.3.2 for
     	# 用列表举例
     	{ % for i in list % }
     		<p>{{ i }}</p>			<!--  i 是vaules,和js不一样(js取的是索引) -->
     		<p>{{ forloop.counter }}:{{ i }}</p>		<!--  输出"索引值:values",索引从1开始 -->
     		<p>{{ forloop.counter0 }}:{{ i }}</p>		<!--  输出"索引值:values",索引从0开始 -->
     		<p>{{ forloop.revcounter }}:{{ i }}</p>		<!--  输出"索引值:values",索引反着打印 -->
     	{ % endfor % }
     	
     	
     	# 用字典举例
     	{ % for i in obj % }	
     		<p>{{ forloop.counter }}:{{ i }}</p>		<!--  输出"索引值:key",索引从1开始,和列表一样 -->
     		<p>{{ forloop.counter }}:{{ i.uname }}</p>		<!--  输出"索引值:values",这样就可以打印值了 -->
     	{ % endfor % }
     	
     	# 字典的使用方法
     	{% for row in user_dict.keys %}
     	{% for row in user_dict.values %}
     	
     	{% for row in user_dict.items %} 得到元组
    
     	{% for k,row in user_dict.items %}
    

   <li>{{k}}-{{row}}</li> {% endfor %}

4.4 过滤器filter
	{{ ship_date|date:"Fj,Y"}}
	ship_date变量传给date过滤器,date过滤器通过使用"Fj,Y"这几个参数来格式化日期数据,
	"|"和unix的管道符类似
	
	
	s = "hello"
	s2 = 1
	s3 = datetime.datetime.now()
	s4 = []
	s5 = "<a rel="nofollow" href="http://www.baidu.com">百度</a>"
	return render(req,"index.html",{"obj":s})
	return render(req,"index.html",{"num":s2})
	return render(req,"index.html",{"time":s3})
	return render(req,"index.html",{"kong":s4})
	return render(req,"index.html",{"a":s5})
	
	<html>
		{{ 对象|方法:参数}}		- 格式
		
		{{ obj }}				- 打印结果"hello".
		{{ obj|upper }}			- 使用模板语言中的upper方法,将"hello"转为大写"HELLO".
		{{ obj|lower }}			- 小写
		{{ obj|firest }}		- 取出第一个字母
		{{ obj|capfirest }}		- 将第一个字母大写
		
		
		{{ num|add:5 }}			- num+5 ,结果为6
		
		{{ 对象|cut: ' '}}		- 去除空格
		{{ time|date: 'Y-m-d'}}		- 输出年月日,"-"也可以写为":"
		
		{{ kong|default: '空的'}}	- 当对象为空时,输出default指定的字符串,如果不为空则输出对象
		
		
		{{ % a % }}				- 会将超链接返回为一个字符串,因为浏览器会认为是不安全的
		
		{ % autoescape off % }	- 这样浏览器就能解析为html语言了,浏览器就认为是安全的
			{{ % a % }}	
		{ % endautoescape % }
		
		{{ a|safe }}			- 这个和上面那个是一样的功能,会告诉浏览器这是安全的
		
		{{ obj|filesizeformat }} -	打印对象的大小
		{{ obj|length }} 		 -	打印对象的长度
		{{ obj|slice: ':-1' }}   -	切片,从头切到最后一个,最后一个不要
		{{ a|urlencode }}
		
		values="hello I am shan"
		{{ values|truncatechars:'6' }}		按字符截取
		{{ values|truncatewords:'2' }}		按单词截取
		
	</html>

	注意:为什么要在前端转而不是后端,试想一下如果输入的是一个字典类型的数据,需要
		for循环完后的数据输出为大写,如果你在后端做这个操作的话就会变得很繁琐,需要
		循环完后赋予一个变量才能转给前端


4.5 中间件 csrf 跨站请求伪造

	用于生成csrf_token的标签,用于防治跨站***验证。

	用于验证form表单
	<form action="/login"  method="post" >
	
		<p>姓名:<input type="text" name="username"></p>
		<p>性别:<input type="text" name="sex"></p>
		<p>邮箱:<input type="text" name="email"></p>
		<p><input type="submit" value="submit"></p>
		{% csrf_token %}		<!-- 指定认证,否则报错Forbidden
								 django会渲染出一个令牌(input标签),
								 拥有类型hidden,名字和值,用于告诉Django,
								 我是一个认证过的表单
								  -->
	</form>
	
	
	注意:
		同时如果你在views.py中返回页面时使用 render_to_response,需要这样写
	
		from django.template import RequestContext,Template
	
		return render_to_response("index.html",context_instent=RequestContext(request))
	
		否则也会报错Forbidden,所以之前才不建议使用render_to_response
	
	
4.6 { % load % } 		- 加载标签库

4.7 { % url % }			- 引用路由配置的地址

4.8 { % with % }		- 用更简单的变量名替代复杂的变量名

	{ % with total=fadsfsadfdsaffdsaf % } {{ total }} { % endwith % }
	
	格式:{ % with 新变量名=旧变量名 % } {{ 新变量名 }} { % endwith % }
	
4.9 { % varbatim % }			- 禁止render
		
	{ % varbatim % }			- name就不会渲染了,输出的就是字符串"{{ name }}	"
		{{ name }}		
	{ % endvarbatim % }
	
4.10 自定义	simple_tag

	需求:比如后端传给了前端一个变量num=1,我想让这个变量在前端+10,
		原本我可以在前端写为 {{ num|add:'10'}},但是我想使用自定义的方法
		{{ num|add100 }},这就叫做自定义simple_tag(简单标签)
		
		
	a. 在app目录下中创建templatetags模块
	b. 创建任意.py文件,如文件名"my_tag.py"
		#!/usr/bin/evn python
		#coding:utf-8
		from django import template
		from django.utils.safestring import mark_safe
		
		register = template.Library()	# register是固定变量名,不能改变
		
		@register.simple_tag			# 装饰器
		def my_add100(v1):
			return v1 + 10				# 实现num+10
			
		@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文件中引入之前创建的mytag.py文件名
		
		{ % load my_tag % }
		
		<html>
		</html>
		
	d. 使用simple_tag
		<html>
			{ % my_add100 1 % }    <!-- 输出11 -->
		</html>
		
		
		<html>
			{ % my_input id1 cl1 % }    <!-- 输出一个input标签,id是id1,class是cl1 -->
		</html>
		
		
4.11 自定义filter
		流程和自定义	simple_tag一样,就差在
		@register.simple_tag了,自定义filter是这样写@register.filter
		
		调用方式为
		{{ num|my_add100 }}			<!-- 输出11 相当于执行"my_add100(num)" -->
		
		如果自定义filter传入的是两个参数,最多也只能两个(自定义	simple_tag没有这个限制),
		解决方法是传入一个列表
		
		@register.filter     			# 装饰器
		def my_add100(v1,v2):
			return v1 + 10 + v2		
		
		{{ num|my_add100:2 }}		<!-- 输出13 -->	
		
		注意:模板的if语句可以加一个自定义filter,但是不能加自定义simple_tag
				同时,使用自定义简单标签和自定义filter,必须在全局文件settings.py中的
				INSTALLED_APPS [
						'myapp',
				]
				区域添加你的app名