小生博客:http://xsboke.blog.51cto.com
小生 Q Q:1770058260
-------谢谢您的参考,如有疑问,欢迎交流
一、静态文件
二、路由映射
三、视图函数
四、template(模板)基础
- 关于静态文件
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>
- 路由映射
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 reret = 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), ]
- 视图函数
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函数,同时也会做一定的判断, 比如用户登录。
- 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 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名
原文地址:http://blog.51cto.com/xsboke/2115458