day 51 django
01.django orm表关系
-
表关系的建立
## 一对多 publish = models.ForeignKey(to='Publish') # Publish为关系表,默认与主键id建立外键 # 外键在创建时,同步到数据中时 表字段会自动加_id后缀 ## 多对多 # 多对多外键字段创建在任意一方都可以,但建议创建在查询频率较高的那一方 author = models.ManyToManyField(to='Author') # django orm会自动帮你创建书籍 和作者的第三张关系表 # author字段是虚拟的不会显示出来 ## 一对一 # 一对一外键字段创建在任意一方都可以,但建议创建在查询频率较高的那一方 author_detail = models.OneToOneField(to='Author_detail')
02.django请求声明周期流程图
03.路由层(urls.py)
-
url第一个参数是一个正则表达式,只要该正则表达式匹配到内容之后就会执行对应的
路由匹配只匹配url不匹配问好后面的内容
url(r'^admin/', admin.site.urls), # url第一个参数是一个正则表达式 url(r'^test/', views.test), # 一旦正则表达式能够匹配到内容 会立刻结束匹配关系 直接执行后面对应的函数
# 不加斜杠 先匹配一次试试 如果匹配不上 会让浏览器重定向 加一个斜杠再来一次 如果还匹配不上 才会报错 """ 路由匹配值匹配url部分 不匹配?后面的get携带的参数 """
-
取消django自动添加/功能
APPEND_SLASH = False # 添加到settings.py文件中
-
无名和无名分组
-
无名分组
url(r'^test/([0-9]{4})/',views.test) # 在正则表达式匹配成功后,会将无名分组内匹配到的值以位置参数的形式传给视图函数 # test(requst,分组内容)
-
有名分组
url(r'^testadd/(?P<year>d+)/', views.testadd) # 当你的路由中有分组并且给分组起了别名 那么在匹配内容的时候 # 会将分组内的正则表达式匹配到的内容当做关键字参数传递给视图函数 testadd(request,year=分组内容)
-
利用分组,可以在调用视图函数之前给函数传递额外的信息
-
有名分组和无名分组不能同时使用,单一种类可以重复使用
-
-
反向解析
根据一个别名 动态解析出一个结果 该结果可以直接访问对应的url
-
情况一没有分组
url(r'^home/', views.home,name='xxx'), # 给路由与视图函数对应关系起别名
{% url 'xxx' %} <!--给前端反向解析-->
from django.shortcuts import render,HttpResponse,redirect,reverse url = reverse('xxx') # 后端反向解析
-
情况二 无名分组
url(r'^home/(d+)/', views.home,name='xxx'), # 给路由与视图函数对应关系起别名
{% url 'xxx', 123 %} <!--给前端反向解析,需要给无名分组添加默认值-->
from django.shortcuts import render,HttpResponse,redirect,reverse url = reverse('xxx', args=(1,)) # 后端反向解析,需要以元组的形式
-
情况三 有名分组
url(r'^home/(?P<year>d+)/', views.home,name='xxx'), # 给路由与视图函数对应关系起别名
{% url 'xxx', 123 %} <!--给前端反向解析,需要给分组添加默认值--> <p><a href="{% url 'xxx' year=1232 %}">111</a></p> <!--更加规范的写法-->
from django.shortcuts import render,HttpResponse,redirect,reverse url = reverse('xxx', args=(1,)) # 后端反向解析,需要以元组的形式 url = reverse('xxx',kwargs={'year':213123}) # 更加规范的写法
-
用法例子
url(r'^edit_user/(d+)/',views.edit_user,name='edit') def edit_user(request,edit_id): # edit_id就是用户想要编辑数据主键值 pass
{% for user_obj in user_list %} <a href='/edit_user/{{user_obj.id}}/'>编辑</a> <a href='{% url 'edit' user_obj.id %}'>编辑</a> {% endfor %}
-
-
路由分发
-
前提
- 在一个django项目中每个app都有自己独立的urls.py、templates.py、static文件夹
- 这样可以做到一个项目分发给多人同时进行开发,当完成后将所有人的app整合到一个空的django项目中
- 在settings.py中配置文件注册 再利用多路由分发将多个app整合到一起完成项目的拼接
- 用来解决总路由匹配关系过多的情况
-
使用路由分发,使总路由不需要做对应关系匹配,只做任务分发(请求来了之后 总路由不做对应关系,值询问要访问的app,然后将其转发给对应的app去处理)
-
写法
## 写法一(复杂) # 在总路由文件,导入个各app的urls文件 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)),
## 写法二 # 不需要导入文件,直接与urlpatterns中进行分发 url(r'^app01/', include('app01.urls')), url(r'^app02/', include('app02.urls'))
# 子路由 from django.conf.urls import url from app01 import views urlpatterns = [ url('^reg/',views.reg) ]
-
-
名称空间
-
当多个app中含有相同的功能别名时会在反向解析时出现冲突
-
我们可以在做路由分发时给每一个app创建一个名称空间,让后在反向解析时可以选择到哪个名称空间中寻找
url(r'^app01/',include('app01.urls',namespace='app01')), url(r'^app02/',include('app02.urls',namespace='app02'))
# 后端 reverse('app01:reg') reverse('app02:reg')
# 前端 <a href="{% url 'app01:reg' %}"></a> <a href="{% url 'app02:reg' %}"></a>
-
在保证其别名的时候,整个django项目中不冲突可以不用名称空间。例如在起别名时统一加上前缀
urlpatterns = [ url(r'^reg/',views.reg,name='app02_reg') ] urlpatterns = [ url('^reg/',views.reg,name='app01_reg') ]
-
-
伪静态
- 将一个动态网页伪装成一个静态网页,页面后缀加.html
-
虚拟环境
- 给每一个项目装备该项目所需要的模块,不需要的模块一概不装
- 虚拟环境就相当于重新下载了一个纯净的python解释器,之后还项目用什么就装什么(一台机器上可以用n多个)
-
django2.0与1.0版本的区别
-
urls.py中路由匹配的方法有区别
# django2.X用的是path urlpatterns = [ path('admin/', admin.site.urls), ] # django1.X用的是url urlpatterns = [ url(r'^reg.html',views.reg,name='app02_reg') ]
-
区别
- django2.X里面path第一个参数不是正则也不支持正则 写什么就匹配什么
- 虽然path不支持正则 感觉也好用 django2.X还有一个re_path的方法 该方法就是你django1.X里面url
- path提供了五种转换器 能够将匹配到的数据自动转换成对应的数据类型
- 除了默认的五种转换器之外,还支持自定义转换器
-
04.视图层
-
form表单上传文件
-
method改成post
-
enctype改成formdata格式
-
前期在使用post请求时需要注释掉settings中的一个中间件csrf
-
django会根据数据类型的不同将文件解析到不同的方法中
# 文件以列表的形式存放于 request.FILES # 获取文件对象 file_obj = request.FILES.get('myfile') # 将文件保存到本地 with open(file_obj.name,'wb') as f: for line in file_obj: f.write(line)
-