自我总结44
表与表的建立方式
ORM` 对象关系映射
表关系 | 解释 | django中建立关系 | 例子 |
---|---|---|---|
一对一 | 数据表数据太多了 一张表拆成两张表,同样两张表可以拼成一张表 外键哪张表都行,建议建在查询频率高的一方 | OneToOne(to='') | 看详情 |
一对多 | 外键在多的那张表 | ForeignKey(to='') | |
多对多 | 外键字段建在任意一方都行,建议建在查询频率高的一方 | ManyToMany(to='') |
一对一外键字段 创建的时候 同步到数据中 表字段会自动加_id后缀,自己不要加
多对多字段不会在表中创建出来 只是用来告诉orm自动帮你创建第三张表能够方便后续orm查询操作
author = models.ManyToManyField(to='Author')
# django orm会自动帮你创建书籍 和作者的第三张关系表
# author这个字段是一个虚拟字段 不能在表中展示出来 仅仅只是起到一个高速orm 建第三章表的关系的作用
django请求生命周期流程图
urls.py 路由层
url第一个参数是一个正则表达式 只要该正则表达式能够匹配到内容就会立刻执行后面的视图函数 而不再往下继续匹配了
正是由于该特点会出现 ,当你的项目特别庞大的时候url会出现被顶替的现象
方法:可以修改正则表达式 / 把下面的url写在上面
django在路由匹配的时候默认有一个补救机制
当你的url没有正常匹配到 django会让浏览器自动加斜杠再来匹配一次(重定向)
配置文件中有一个参数用来控制该机制是否允许
APPEND_SLASH = True/False
网站首页可以使用的匹配方式
# 网站首页
url(r'^$',home),
# 网站404页面的设计(了解)
url(r'',error)
路由匹配
django 路由匹配的规律
先不加/
让浏览器先匹配 ,如果匹配不上让浏览器重定向,加/
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls), # url第一个参数是一个正则表达式
url(r'^test/$', views.test), # 一旦正则表达式能够匹配到内容 会立刻结束匹配关系 直接执行后面对应的函数
url(r'^testadd/$', views.testadd),
]
"""
路由匹配值匹配url部分
不匹配?后面的get携带的参数
"""
取消django自动让浏览器加/
功能
APPEND_SLASH = False # 默认是True
无名分组
将分组内正则表达式匹配到的内容当做位置实参传递给视图函数
url(r'^test/([0-9]{4})/', views.test)
test() takes 1 positional argument but 2 were given
# 当你的路由中有分组的正则表达式 那么在匹配到内容
# 执行视图函数的时候 会将分组内正则表达式匹配到的内容当做位置参数传递给视图函数 test(request,分组内正则表达式匹配到的内容)
有名分组
会将分组内的正则表达式匹配到的内容当做关键字参数传递给视图函数
url(r'^testadd/(?P<year>\d+)/', views.testadd),
testadd() got an unexpected keyword argument 'year'
# 当你的路由中有分组并且给分组起了别名 那么在匹配内容的时候
# 会将分组内的正则表达式匹配到的内容当做关键字参数传递给视图函数 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'), # 给路由与视图函数对应关系起别名
前端反向解析
<p><a href="{% url 'xxx' 12 %}">111</a></p>
<p><a href="{% url 'xxx' 1324 %}">111</a></p>
<p><a href="{% url 'xxx' 14324 %}">111</a></p>
<p><a href="{% url 'xxx' 1234 %}">111</a></p>
后端反向解析
url = reverse('xxx',args=(1,))
url1 = reverse('xxx',args=(3213,))
url2 = reverse('xxx',args=(2132131,))
# 手动传入的参数 只需要满足能够被正则表达式匹配到即可
第三种情况
有名分组的反向解析 在解析的时候 你需要手动指定正则匹配的内容是什么有名分组的反向解析可以跟无名分组一样
url(r'^home/(?P<year>\d+)/', views.home,name='xxx'), # 给路由与视图函数对应关系起别名
前端反向解析
# 可以直接用无名分组的情况
<p><a href="{% url 'xxx' 12 %}">111</a></p>
# 你也可以规范写法
<p><a href="{% url 'xxx' year=1232 %}">111</a></p> # 了解即可
后端反向解析
# 可以直接用无名分组的情况
url = reverse('xxx',args=(1,))
# 你也可以规范写法
url = reverse('xxx',kwargs={'year':213123}) # 了解即可
路由分发
路由分发解决的就是项目的总路由匹配关系过多的情况
总路由不再直接做路g'neng'i由和视图函数对应关系了,而是仅仅做一个转发的功能
好处:更加解耦合,更加好维护
应用场景:在django中所有的app都可以有自己独立的urls.py templates static
正是由于上面的特点 你用django开发项目就能够完全做到多人分组开发 互相不干扰
每个人只开发自己的app
小组长只需要将所有人开发的app整合到一个空的django项目里面
然后在settings配置文件注册 再利用路由分发将多个app整合到一起即可完成大项目的拼接
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
# url第一个参数是一个正则表达式
# 路由分发
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('^reg/',views.reg)
]
from django.conf.urls import url
from app02 import views
urlpatterns = [
url('^reg/',views.reg)
]
名称空间(了解)
当多个app中出现了起别名冲突的情况,你在做路由分发的时候,可以给每一个app创建一个名称空间
然后在反向解析的时候 可以选择到底去哪个名称空间中查找别名
url(r'^app01/',include('app01.urls',namespace='app01'))
# 后端
print(reverse('app01:reg'))
print(reverse('app02:reg'))
# 前端
<a href="{% url 'app01:reg' %}"></a>
<a href="{% url 'app02:reg' %}"></a>
为了不造成上述情况,建议:起别名的时候统一加上应用名前缀
参考建议
起别名的时候统一加上应用名前缀
urlpatterns = [
url(r'^reg/',views.reg,name='app02_reg')
]
urlpatterns = [
url('^reg/',views.reg,name='app01_reg')
]
伪静态
将一个动态网页伪装成一个静态网页 以此来挺好搜索引擎SEO查询频率和搜藏力度所谓的搜索引擎其实就是一个也别巨大的爬虫程序
虚拟环境
给每一个项目 提供该项目专门所需要的模块 不需要的模块一概不装
每创建一个虚拟环就类似于你重新下载了一个纯净python解释器
之后该项目用到上面 你就装什么 (虚拟环境一台机器上可以有N多个)
django版本区别
django1.x django2.x
# 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
第一个参数不是正则也不支持正则 写什么就匹配什么
django2.X
还有一个re_path
的方法 该方法就是你django1.X
里面url
path
五种转换器
能够将匹配到的数据自动转换成对应的类型
自定义转换器
支持
view.py 视图层
form表单默认是get请求,get请求也是能够携带参数
# 特点
url?xxx=xxx&yyy=yyy
例:http://127.0.0.1:8000/login/?username=jason&password=jason123
- 携带的数据和不安全
- 携带的数据大小有限制
- 通常只会携带一些不是很重要的数据
action
- 不写默认朝当前地址提交
- 只写后缀 /index
- 写全路径 https://www.baidu.com
注:前期你在使用post朝后端发请求的时候 需要去settings配置文件中注释掉一个中间件csrf
# 中间件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
django 后端默认处理的是get请求
无论是get请求还是post请求 都会执行视图函数
def login(request):
print('来啦 老弟~')
return render(request,'login.html')
get请求指向拿到login页面
post请求想提交数据 然后后端做校验
form表单上传文件 后端如何获取文件
form表达传文件需要注意的事项:
1.method必须改成post
2.enctype该成formdata格式
request.FILES
获取form表单上传的文件数据