您好,登录后才能下订单哦!
小生博客:http://xsboke.blog.51cto.com
-------谢谢您的参考,如有疑问,欢迎交流
一、静态文件
二、路由映射
三、视图函数
四、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 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),
]
视图函数
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名
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。