Djiango各组成部分及功能介绍
一、复习
1.启动django项目: python3 manage.py runserver 127.0.0.1:8801(端口号) 2.创建app的三种方法:django-admin startapp app01 | python3 manage.py startapp app02 | pycharm的Tools下 Run manage.py task..
manage.py@dg64_1 > startapp app06 3.基础流程:配置url -> 定义视图函数 -> 完成请求响应 -> 与模板及数据库交互 4.静态文件配置:在settings中配置静态文件存放的路径,在页面中按配置路径引入 5.数据库交互:settings配置 -> init中替换数据库操作模块 -> 创建Model类 -> 迁移数据 python3 manage.py makemigrations python3 manage.py migrate 6.记录的增删改查:User.objects.filter(id=1).all() | user.save()
二、路由基础
# 正则路径 视图函数地址 默认关键字参数(了解) 路由别名 # ^表示开头匹配(只能匹配以^后面的字符开头) $表示结尾匹配(只能匹配以$后面的字符结尾) # r'^index$' 只能匹配index,不能匹配index/ # r'^index/$' 只能匹配index/,能匹配index(先拿index匹配,如果失败,会添加/再次匹配) url(r'^index/$', views.index) url(r'^testkw/$', views.testkw, {'num': 88888}) # def testkw(request, num): # num为关键字参数,此处已固定死,传给testkw 意义不大,因此不常用 # 路由匹配时是否会默认添加/ # 'django.middleware.common.CommonMiddleware' 控制APPEND_SLASH的中间件 # APPEND_SLASH = False # django中此值默认为True
三、有名无名分组
# 无名分组:/testnoname/10/ url(r'^testnoname/(\d+)/$', views.testnoname) # django自动将testnoname和(\d+)匹配到值和的以位置参数的形式传给views.testnoname,因此testnoname函数中可以用任意变量接受(\d+)匹配到值 # def testnoname(request, var) # var=10 # 有名分组:/testname/10/1/ url(r'^testname/(?P<num>\d+)/(?P<page>\d+)/$', views.testname) # django自动将(?P<num>\d+)/(?P<page>\d+)匹配到值和的以关键字参数的形式传给views.testname,因此testname函数中只能用对应的关键字接受(?P<num>\d+)/(?P<page>\d+)匹配到值 # def testname(request, page, num) # page=1 num=10 # 注:有名分组和无名分组不能混用(如果混用,无名参数无法接受)
四、多app共存的路由分配
# 在主路由中药配置多个app,要对视图函数调用起别名 from app01 import views as app01_views from app02 import views as app02_views url(r'^app01/test_page/$', app01_views.test_page), url(r'^app02/test_page/$', app02_views.test_page),
五、多app共存时模板冲突问题
方法1:在对应应用下建立自己的templates,再在templates下建立与应用名同名的文件夹,模板文件放在应用名同名的文件夹下 方法2:在项目根目录下的templates中建立每一个应用同名的文件夹,每个应用的模板文件放在自己应用名文件夹下 使用:render(request, 'app_name/test.html')
六、创建app流程
1. python3 manage.py startapp app_name 2. 去settings中配置INSTALLED_APPS, 添加记录:'app_name.apps.App_nameConfig' # 注:app配置的顺序决定了(共同资源冲突下的)查找顺序
七、路由分发
# 分担总路由的代码压力, 将每个app的自身路由配置交给app自己的urls.py来管理(分文件管理路由) 1.在每一个应用中建立自身的urls.py文件,语法同主路由 2.在主路由进行分发 from django.conf.urls import include urlpatterns = [ url(r'^app01/', include('app01.urls')), #将请求路径自动拆分,主路由根据第一部分进行分发 url(r'^app02/', include('app02.urls')), ] # 注:主路由分发一定不能使用$正则语法 (错误eg: ^app01/$)
八、路由别名
1.有些路由会被大量访问(直接访问、间接访问) 2.这些路由可能后期还会发生变化 3.可以给路由设置别名,通过别名访问:<a href="{% url '路由别名' '传入有名无名分组所需参数' %}"></a> url(r'^index/$', views.index, name= "index" ) # name为给路由设置的别名,可以通过别名访问
九、名称空间
主路由: from django.conf.urls import include urlpatterns = [ url(r'^app01/', include('app01.urls', namespace='app01')), url(r'^app02/', include('app02.urls', namespace='app02')), ] app01应用下路由 from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^test/', views.test, name='test') ] app02应用下路由 from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^test/', views.test, name='test') ] 前端页面反向解析:{% url 'app01:test' %} | {% url 'app02:test' %} 视图函数reverse方法:url = reverse('app01:test') | url = reverse('app02:test')
十、反向解析
from django.shortcuts import reverse 在视图函数中通过reverse方法反向解析出真实的路径 # 1.不带分组:url(r'可能会变的真实路由', 视图函数, name='路由别名') url = reverse('路由别名') # 2.无名分组:url(r'可能会变的真实路由(带无名分组)', 视图函数, name='路由别名') url = reverse('路由别名', args=(给无名分组赋值)) # 3.有名分组:url(r'可能会变的真实路由(带有名分组)': 视图函数, name='路由别名') url = reverse('路由别名', kwargs={给有名分组赋值:key就是有名分组名})
十一、2.x新特性
from django.urls import path, re_path # 向下兼容,不建议使用url, 使用与url相同的re_path from django.conf.urls import url urlpatterns = [ path('index/', views.index), # page/<int:msg>/ page/(?P<msg>(\d+)) # 访问/page/123/ # path('page/<int:msg>/', views.page), # path('page/<str:msg>/', views.page), # path('page/<path:msg>/', views.page), # path('page/<slug:msg>/', views.page), path('page/<uuid:msg>/', views.page), ] # 1. 2.x版本re_path的使用方式同1.x版本url # 2. path写的是绝对字符串,请求地址必须与路由地址完全匹配 # 3. path拥有五个转换器: -- str:匹配除路径分隔符(/)外的字符串,默认 -- int:匹配自然数 -- slug:匹配字母、数字、横杠及下划线组成的字符串 -- uuid:匹配uuid形式的数据 -- path:匹配任何字符串,包括路径分隔符(/) (不能用?)
十二、自定义转换器
# 原因:自定义正则匹配目标路径 语法: 1.自定义类 # 匹配11位的185电话 class CVT185phone: # 匹配过程 regex = '185\d{8}' def to_python(self, value): return int(value) # 反解过程 def to_url(self, value): # return '%11d' % value return '18500079888' ----settings.py # 在主路由中 from django.urls import register_converter from 所在路径 import CVT185phone register_converter(CVT185phone, 'phone185') urlpatterns = [ path('index/', views.index), path('page/<phone185:msg>/', views.page, name="pages"), ] ----views.py def index(request): url = reverse('pages', kwargs={'msg': 18512345678}) print(url) return redirect(url) def page(request, msg): print(msg) print(type(msg)) return HttpResponse("page %s" % msg) 程序运行顺序:浏览器(http://127.0.0.1:8801/index/)发送请求index到url中执行views中的index函数,reverse反向解析跳转到自定义类CVT185phone中执行to_url函数并返回为page/18500079888然后,此时将page和msg=18500079888传给views中的page函数继续向下执行。