1. 路由层
url( r'test' , views. test) ,
url( r'testadd' , views. testadd)
"""
url方法第一个参数是正则表达式
只要第一个参数正则表达式能够匹配到内容 那么就会立刻停止往下匹配
直接执行对应的视图函数
在输入url的时候会默认加斜杠
django内部帮你做到重定向
一次匹配不行
url后面加斜杠再来一次
"""
APPEND_SLASH = False / True
urlpatterns = [
url( r'^admin/' , admin. site. urls) ,
url( r'^$' , views. home) ,
url( r'^test/$' , views. test) ,
url( r'^testadd/$' , views. testadd) ,
url( r'' , views. error) ,
]
1. 无名分组
"""
分组:就是给某一段正则表达式用小括号扩起来
"""
url( r'^test/(\d+)/' , views. test)
def test ( request, xx) :
print ( xx)
return HttpResponse( 'test' )
2. 有名分组
"""
可以给正则表达式起一个别名
"""
url( r'^testadd/(?P<year>\d+)' , views. testadd)
def testadd ( request, year) :
print ( year)
return HttpResponse( 'testadd' )
3. 无名有名是否可以混合使用?
"""
不能混用
但是同一个分组可以使用N多次
"""
url( r'^index/(\d+)/(\d+)/(\d+)/' , views. index) ,
url( r'^index/(?P<year>\d+)/(?P<age>\d+)/(?P<month>\d+)/' , views. index) ,
def index ( request, * args, ** kwargs) :
print ( args)
print ( kwargs)
return HttpResponse( 'index' )
4. 反向解析
url( r'^func_kkk/' , views. func, name= 'ooo' )
from django. shortcuts import reverse
reverse( 'ooo' )
< a href= "{% url 'ooo' %}" > 111 < / a>
5. 无名有名分组反向解析
url( r'^index/(\d+)/' , views. index, name= 'xxx' )
{ % url 'xxx' 123 % }
reverse( 'xxx' , args= ( 1 , ) )
def edit ( request, edit_id) :
reverse( 'xxx' , args= ( edit_id, ) )
{ % for user_obj in user_queryset% }
< a href= "{% url 'xxx' user_obj.id %}" > 编辑< / a>
{ % endfor% }
url( r'^func/(?P<year>\d+)/' , views. func, name= 'ooo' )
< a href= "{% url 'ooo' year=123 %}" > 111 < / a> 了解
< a href= "{% url 'ooo' 123 %}" > 222 < / a> 常用
print ( reverse( 'ooo' , kwargs= { 'year' : 123 } ) )
print ( reverse( 'ooo' , args= ( 111 , ) ) )
6. 路由分发
"""
django的每一个应用都可以有自己的templates文件夹 urls.py static文件夹
利用路由分发之后 总路由不再干路由与视图函数的直接对应关系
而是做一个分发处理
识别当前url是属于哪个应用下的 直接分发给对应的应用去处理
"""
from django. conf. urls import url, include
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
url( r'^app01/' , include( app01_urls) ) ,
url( r'^app02/' , include( app02_urls) )
url( r'^app01/' , include( 'app01.urls' ) ) ,
url( r'^app02/' , include( 'app02.urls' ) )
]
from django. conf. urls import url
from app01 import views
urlpatterns = [
url( r'^reg/' , views. reg)
]
from django. conf. urls import url
from app02 import views
urlpatterns = [
url( r'^reg/' , views. reg)
]
7. 名称空间
"""
正常情况下的反向解析是没有办法自动识别前缀的
"""
url( r'^app01/' , include( 'app01.urls' , namespace= 'app01' ) ) ,
url( r'^app02/' , include( 'app02.urls' , namespace= 'app02' ) )
urlpatterns = [
url( r'^reg/' , views. reg, name= 'reg' )
]
urlpatterns = [
url( r'^reg/' , views. reg, name= 'reg' )
]
reverse( 'app01:reg' )
reverse( 'app02:reg' )
{ % url 'app01:reg' % }
{ % url 'app02:reg' % }
"""
一般情况下 有多个app的时候我们在起别名的时候会加上app的前缀
这样的话就能够确保多个app之间名字不冲突的问题
"""
urlpatterns = [
url( r'^reg/' , views. reg, name= 'app01_reg' )
]
urlpatterns = [
url( r'^reg/' , views. reg, name= 'app02_reg' )
]
2. django版本区别
"""
1.django1.X路由层使用的是url方法
而在django2.X和3.X版本中路由层使用的是path方法
url()第一个参数支持正则
path()第一个参数是不支持正则的 写什么就匹配什么
如果习惯使用path那么也给你提供了另外一个方法
from django.urls import path, re_path
from django.conf.urls import url
re_path(r'^index/',index),
url(r'^login/',login) # 如果非要写url,则这样导入。但不推荐
2.X和3.X里面的re_path就等价于1.X里面的url
2.虽然path不支持正则 但是它的内部支持五种转换器
path('index/<int:id>/',index)
# 将第二个路由里面的内容先转成整型然后以关键字的形式传递给后面的视图函数
def index(request,id):
print(id,type(id))
return HttpResponse('index')
# 5个转换器
1. str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
2. int,匹配正整数,包含0。
3. slug,匹配字母、数字以及横杠、下划线组成的字符串。
4. uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
5. path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
3.除了有默认的五个转换器之外 还支持自定义转换器(了解)
class MonthConverter:
regex='\d{2}' # 属性名必须为regex
def to_python(self, value):
return int(value)
def to_url(self, value):
return value # 匹配的regex是两个数字,返回的结果也必须是两个数字
# 使用方法
from django.urls import path,register_converter
from app01.path_converts import MonthConverter
# 先注册转换器
register_converter(MonthConverter,'mon')
from app01 import views
urlpatterns = [
path('articles/<int:year>/<mon:month>/<slug:other>/', views.article_detail, name='aaa'),
]
4.模型层里面1.X外键默认都是级联更新删除的
但是到了2.X和3.X中需要你自己手动配置参数
models.ForeignKey(to='Publish') # 1.x
models.ForeignKey(to='Publish',on_delete=models.CASCADE...) # 2.x和3.x
"""
3. 视图层
1. JsonResponse对象
import json
from django. http import JsonResponse
def ab_json ( request) :
user_dict = { 'username' : 'haha的世界' , 'pwd' : '123' }
return JsonResponse( user_dict, json_dumps_params= { 'ensure_ascii' : False } )
2. form表单上传文件及后端如何操作
"""
form表单上传文件类型的数据
1.method必须指定成post
2.enctype必须换成formdata
"""
def ab_file ( request) :
if request. method == 'POST' :
print ( request. FILES)
file_obj = request. FILES. get( 'file' )
print ( file_obj. name)
with open ( file_obj. name, 'wb' ) as f:
for line in file_obj. chunks( ) :
f. write( line)
return render( request, 'form.html' )
3. request对象方法
"""
request.method
request.POST
request.GET
request.FILES # 获取上传的文件
request.body # 原生的浏览器发过来的二进制数据
request.path
request.path_info # 与request.path 相同
request.get_full_path() 能过获取完整的url及问号后面的参数
"""
print ( request. path)
print ( request. path_info)
print ( request. get_full_path( ) )
4. FBV与CBV
def index ( request) :
return HttpResponse( 'index' )
url( r'^login/' , views. MyLogin. as_view( ) )
from django. views import View
class MyLogin ( View) :
def get ( self, request) :
return render( request, 'form.html' )
def post ( self, request) :
return HttpResponse( 'post方法' )
"""
FBV和CBV各有千秋
CBV特点
能够直接根据请求方式的不同直接匹配到对应的方法执行
"""
4. 模板层
1. 模版语法传值
def index ( request) :
n = 123
f = 11.11
s = '我也想奔现'
b = True
l = [ '小红' , '姗姗' , '花花' , '茹茹' ]
t = ( 111 , 222 , 333 , 444 )
d = { 'username' : 'jason' , 'age' : 18 , 'info' : '这个人有点意思' }
se = { '晶晶' , '洋洋' , '嘤嘤' }
def func ( ) :
print ( '我被执行了' )
return '你的另一半在等你'
class MyClass ( object ) :
def get_self ( self) :
return 'self'
@staticmethod
def get_func ( ) :
return 'func'
@classmethod
def get_class ( cls) :
return 'cls'
def __str__ ( self) :
return '到底会不会?'
obj = MyClass( )
return render( request, 'index.html' , locals ( ) )
< p> { { n } } < / p>
< p> { { f } } < / p>
< p> { { s } } < / p>
< p> { { b } } < / p>
< p> { { l } } < / p>
< p> { { d } } < / p>
< p> { { t } } < / p>
< p> { { se } } < / p>
< p> 传递函数名会自动加括号调用 但是模版语法不支持给函数传额外的参数: { { func } } < / p>
< p> 传类名的时候也会自动加括号调用( 实例化) { { MyClass } } < / p>
< p> 内部能够自动判断出当前的变量名是否可以加括号调用 如果可以就会自动执行 针对的是函数名和类名< / p>
< p> { { obj } } < / p>
< p> { { obj. get_self } } < / p>
< p> { { obj. get_func } } < / p>
< p> { { obj. get_class } } < / p>
< p> { { d. username } } < / p>
< p> { { l. 0 } } < / p>
< p> { { d. hobby. 3. info } } < / p>
2. 过滤器(过滤器只能最多有两个参数)
{ { 数据| 过滤器: 参数} }
< h1> 过滤器< / h1>
< p> 统计长度: { { s| length } } < / p>
< p> 默认值( 第一个参数布尔值是True 就展示第一个参数的值否在展示冒号后面的值) : { { b| default: '啥也不是' } } < / p>
< p> 文件大小: { { file_size| filesizeformat } } < / p>
< p> 日期格式化: { { current_time| date: 'Y-m-d H:i:s' } } < / p>
< p> 切片操作( 支持步长) : { { l| slice : '0:4:2' } } < / p>
< p> 切取字符( 包含三个点) : { { info| truncatechars: 9 } } < / p>
< p> 切取单词( 不包含三个点 按照空格切) : { { egl| truncatewords: 9 } } < / p>
< p> 切取单词( 不包含三个点 按照空格切) : { { info| truncatewords: 9 } } < / p>
< p> 移除特定的字符: { { msg| cut: ' ' } } < / p>
< p> 拼接操作: { { l| join: '$' } } < / p>
< p> 拼接操作( 数值加法) : { { n| add: 10 } } < / p>
< p> 拼接操作( 字符串拼接) : { { s| add: msg } } < / p>
< p> 转义: { { hhh| safe } } < / p>
< p> 转义: { { res } } < / p>
| safe
from django. utils. safestring import mark_safe
res = mark_safe( '<h1>新新</h1>' )
3. 标签
{ % for foo in l % }
< p> { { forloop } } < / p>
< p> { { foo } } < / p>
{ % endfor % }
{ 'parentloop' : { } , 'counter0' : 0 , 'counter' : 1 , 'revcounter' : 6 , 'revcounter0' : 5 , 'first' : True , 'last' : False }
{ % if b % }
< p> baby< / p>
{ % elif s % }
< p> 都来把< / p>
{ % else % }
< p> 老baby< / p>
{ % endif % }
{ % for foo in lll % }
{ % if forloop. first % }
< p> 这是第一次< / p>
{ % elif forloop. last % }
< p> 这是最后一次啊< / p>
{ % else % }
< p> { { foo } } < / p>
{ % endif % }
{ % empty % }
< p> for 循环的可迭代对象内部没有元素 根本没法循环< / p>
{ % endfor % }
{ % for foo in d. keys % }
< p> { { foo } } < / p>
{ % endfor % }
{ % for foo in d. values % }
< p> { { foo } } < / p>
{ % endfor % }
{ % for foo in d. items % }
< p> { { foo } } < / p>
{ % endfor % }
{ % with d. hobby. 3. info as nb % }
< p> { { nb } } < / p>
在with 语法内就可以通过as 后面的别名快速的使用到前面非常复杂获取数据的方式
< p> { { d. hobby. 3. info } } < / p>
{ % endwith % }
4. 自定义过滤器、标签、inclusion_tag
"""
三步走
1.在应用下创建一个名字“必须”叫templatetags文件夹
2.在该文件夹内创建“任意”名称的py文件 eg:mytag.py
3.在该py文件内"必须"先书写下面两句话(单词一个都不能错)
from django import template
register = template.Library()
"""
from django import template
register = template. Library( )
@register. filter ( name= 'baby' )
def my_sum ( v1, v2) :
return v1 + v2
{ % load mytag % }
< p> { { n| baby: 666 } } < / p>
@register. simple_tag ( name= 'plus' )
def index ( a, b, c, d) :
return '%s-%s-%s-%s' % ( a, b, c, d)
标签多个参数彼此之间空格隔开
< p> { % plus 'jason' 123 123 123 % } < / p>
"""
内部原理
先定义一个方法
在页面上调用该方法 并且可以传值
该方法会生成一些数据然后传递给一个html页面
之后将渲染好的结果放到调用的位置
"""
@register. inclusion_tag ( 'left_menu.html' )
def left ( n) :
data = [ '第{}项' . format ( i) for i in range ( n) ]
return locals ( )
{ % left 5 % }
< ul>
{ % for foo in data % }
< li> { { foo } } < / li>
{ % endfor % }
< / ul>
5. 模版的继承
"""
页面整体都相同 只是某一些局部在做变化
"""
{ % extends 'home.html' % }
{ % block content % }
模版内容
{ % endblock % }
{ % block content % }
子页面内容
{ % endblock % }
1. css区域
2. html区域
3. js区域
{ % block css % }
{ % endblock % }
{ % block content % }
{ % endblock % }
{ % block js % }
{ % endblock % }
6. 模版的导入
"""
将页面的某一个局部当成模块的形式
哪个地方需要就可以直接导入使用即可
"""
{ % include 'wasai.html' % }