orm表关系如何建立
多对多
一对多
一对一
from django.db import models
# Create your models here.
class Book(models.Model): # 图书表
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2) # 小数(总位数,小数点后位数)
publish = models.ForeignKey(to='Publish') # 一对多 # to用来指定跟那张表有关系
# 外键建议加在查询频率较高的那张表
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): # 作者表
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='Author_detail') # 一对一
class Author_detail(models.Model): # 作者详情表
phone = models.BigIntegerField()
addr = models.CharField(max_length=32)
注意:
一对多外键字段 创建的时候 同步到数据中 表字段会自动加 _id后缀
如果你自己加了 orm依然会加上 _id
所以不要自作聪明加 _id
django请求生命周期流程图
是后期复习django最好的方式
urls.py 路由层
url第一个参数是一个正则表达式 只要该正则表达式能够匹配到内容就会立刻执行后面的视图函数 而不会往下继续匹配了
路由匹配
# 取消django自动让浏览器加斜杠的功能
APPEND_SLASH = False # 该参数默认是True
from app01 import views
urlpatterns = [
url(r'^admin/',admin.site.urls), # url第一个参数是一个正则表达式
url(r'^test/$',views.test), # 一旦正则表达式能够匹配到内容 会立刻结束匹配关系 直接执行后面对应的函数
url(r'^testadd/$',views.testadd),
]
# django匹配路由的规律
# 不加斜杠 先匹配一次试试 如果匹配不上 会让浏览器重定向 加一个斜杠再来一次 如果还匹配不上 才会报错
路由匹配值匹配url部分 不匹配?后面的get携带的参数
无名分组: 将分组内正则表达式匹配到的内容当作位置的参数传递给视图函数
url(r'test/([0-9]{4})/',views.test)
test() takes 1 postition 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.index),
不能混合使用!!!
但是同一种分组的情况下 可以使用多次
无名可以有多个
有名可以有多个
但是就是不能混合使用
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 improt 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}) # 了解即可
以编辑功能为例
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
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表单上传文件需要注意的事项
1.method必须改成post
2.enctype该成formdata格式
前期你在使用post朝后端发请求的时候 需要去settings配置文件中注释掉一个中间件csrf