orm 表关系如何建立
多对多:外键字段在任意一方都可以,建议建在查询频率高的表,其外键关系需要建立第三张表来专门处理。
一对多:外键在多的那个表里
一对一:外键建议建在查询频率高的表
换位思考:先分析一张表 然后分析另一张表
创建表的时候,先创基表 再创建有外键的
- 本周大作业:图书管理系统
- 图书表
- 出版社表
- 作者表
from django.db import models # Create your models here. #先不考虑外键关系 先创建基表 class Book(models.Model): title=models.CharField(max_length=32) #小数共8位,小数点占两位 price=models.DecimalField(max_digits=8,decimal_places=2) #书跟出版社是一对多,并且书是多的一方 所以外键字段键在书表中 publish=models.ForeignKey(to='Publish') #to用来指代跟哪张表有关系 默认关联的是表的主键字段 ''' 一对多外键字段 创建的时候 同步到数据中 表字段会自动加_id后缀 如果你自己加了_id orm还是会再加一个_id 所以写外键字段的时候不用自己加_id ''' #书和作者是多对多关系 外键字段建在任意一方都可以 但是建议建在查询频率高的那一方 author=models.ManyToManyField(to='Author') #这样写django orm会自动帮你创建书籍 和作者的第三张关系表 #author这个字段是一个虚拟字段 不能在表中展示出来 仅仅只是告诉orm建第三张表关系的作用 class Publish(models.Model): title=models.CharField(max_length=32) email=models.EmailField() class Author(models.Model): title=models.CharField(max_length=32) email=models.EmailField() #一对一的表关系 外键字段建在任意一方都可以 但是建议建在查询频率高的一方 author_detail=models.OneToOneField(to='Author_detail') #fk+unique ''' 一对一外键字段 创建的时候 同步到数据中 表字段会自动加_id后缀 如果你自己加了_id orm还是会再加一个_id 所以写外键字段的时候不用自己加_id ''' class Author_detail(models.Model): phone=models.BigIntegerField() addr=models.CharField(max_length=32)
url.py
url第一个参数是正则表达式 只要该正则表达式能够匹配到内容,就会立即执行后面的视图函数 不再往下继续匹配了
路由匹配
django匹配路由的规律:
不加斜杠 先匹配一次试试 如果匹配不上 会让浏览器重定向(301) 加一个斜杠再来一次 如果还匹配不上才会报错
取消django自动让浏览器加斜杠的功能:
APPEND_SLASH=False 该参数默认是True urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^test/$',views.test), #$加^能明确限制匹配的内容 ]
- 路由匹配只匹配url部分,不匹配?后面的get请求携带的参数
无名分组
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^test/[0-9]{4}/',views.test), #test/后面必须是4位0-9的数字 url(r'^test/([0-9]{4})/',views.test), url(r'^test/(/d+)/',views.test), #/d+表示一个或多个数字 ]
- 正则表达式里加括号表示分组,用re.findall()查找优先展示的是分组的内容
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(r'^index/(\d+)/(?P<year>\d+)/',views.testadd),
- 但是同一种分组的情况下 可以使用多次,无名可以有多个,有名可以有多个。
url(r'^index/(\d+)/(\d+)/', views.index), url(r'^index/(?P<args>\d+)/(?P<year>\d+)/', views.index),
反向解析
根据一个别名 动态解析出一个结果 该结果可以直接访问对应的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=(333,)) url2=reverse('xxx',args=(456,))
手动传入的参数 只需要满足能够被正则表达式匹配到即可
第三种情况
- 有名分组的反向解析 在解析的时候 需要手动指定正则匹配的内容是什么,有名分组的反向解析可以跟无名分组一样,但是最正规的写法是
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=12 %}">111</a></p>
- 后端
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 static
正是由于上面的特点 你用django开发项目就能够完全做到多人分组开发 互相不干扰
每个人只开发自己的app
小组长只需要将所有人开发的app整合到一个空的django项目里面 然后在settings配置文件注册 再利用路由分发将多个app整合到一起即可完成大项目的拼接
路由分发解决的就是项目的总路由匹配关系过多的情况
使用路由分发 会将总路由不再做匹配的活
而仅仅是做任务分发(请求来了之后 总路由不做对应关系 只询问你要访问哪个app的功能 然后将请求转发给对应的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)), ] # 子路由 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) ] 最省事的写法(******) url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls')) 名称空间 当多个app中出现了起别名冲突的情况 你在做路由分发的时候 可以给每一个app创建一个名称空间 然后在反向解析的时候 可以选择到底去哪个名称空间中查找别名 url(r'^app01/',include('app01.urls',namespace='app01')), url(r'^app02/',include('app02.urls',namespace='app02')) # 后端 print(reverse('app01:reg')) print(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') ]
伪静态
将一个动态网页伪装成一个静态网页 以此来提高搜索引擎SEO查询频率和搜索力度
所谓的搜索引擎其实就是一个也别巨大的爬虫程序
优化的再厉害还是抵不过RMB玩家
虚拟环境
给每一个项目 装备该项目所需要的模块 不需要的模块一概不装 每创建一个虚拟环境就类似于你重新下载了一个纯净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第一个参数不是正则也不支持正则 写什么就匹配什么
- 虽然path不支持正则 感觉也好用 django2.X还有一个re_path的方法 该方法就是你django1.X里面url
- 虽然path支持 但是它提供了五种转换器 能够将匹配到的数据自动转黄成对应的类型
- 除了有默认五种转换器之外 还支持你自定义转换器
form表单上传文件 后端如何获取文件
form表单传达需要注意的事项
- method必须改成post
- enctype改成form_data格式
前期你在使用post朝后端发请求的时候 需要去settings配置文件中注释掉一个中间件csrf