一 orm外键建立
#1.一对一关系(随便建立在那张表中,推荐建立在查询频率高的表中) 字段名 = models.OneToOneField(to=关联表名,null=True) 例: author_detail = models.OneToOneField(to='AuthorDetail',null=True) #2.一对多关系(外键建立在多关系的表中) 字段名 = models.ForeignKey(to=关联表名) 例: publish = models.ForeignKey(to='Publish') # to表示的就是跟哪张表是一对多的关系 默认都是跟表的主键字段建立关系
# publish = models.ForeignKey(to=Publish) # to后面也可以直接写表名 但是必须保证表名在上面
#3.多对多(随便建立在任何一张表中,不需要自己手动建立第三张表orm会帮你键)
字段名 = models.ManyToManyField(to=关联表名)
例: authors = models.ManyToManyField(to='Author') # 不会在表中生成authors字段 该字段是一个虚拟字段 仅仅是用来告诉django orm自动帮你创建书籍和作者的第三张关系表
注意: 1.第三张表名为:当前字段所在: 类名(表名)_字段名,字段为:两张表名_主键 例: book_authors ,id book_id author_id
2.前面两个关键字会自动再字段后面加_id 最后一个关键字 并不会产生实际字段 只是告诉django orm自动创建第三张表
补充小叔子段:
# 共8位 小数部分占两位
price = models.DecimalField(max_digits=8,decimal_places=2)
图书管理系统案例orm模型表设计:
1.book表,2.author表 3.publish表 4.authordetail表 12多对多 ,13一对多 ,24一对一 from django.db import models # Create your models here. class Book(models.Model): # id自动创建 可以不写 title = models.CharField(max_length=64) # 共8位 小数部分占两位 price = models.DecimalField(max_digits=8,decimal_places=2) # 书籍和出版社是一对多的外键关系 publish = models.ForeignKey(to='Publish') # to表示的就是跟哪张表是一对多的关系 默认都是跟表的主键字段建立关系 """ 只要是ForeignKey的字段 django orm在创建表的时候 会自动在一对多的字段名之后加_id 如果你自己加了 不管 还会继续往后加 """ # publish = models.ForeignKey(to=Publish) # to后面也可以直接写表名 但是必须保证表名在上面 # 书籍和作者是多对多的关系 authors = models.ManyToManyField(to='Author') # 不会在表中生成authors字段 该字段是一个虚拟字段 仅仅是用来告诉django orm自动帮你创建书籍和作者的第三张关系表 class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() # 作者与作者详情 是一对一的外键关系 author_detail = models.OneToOneField(to='AuthorDetail',null=True) """ 也会自动再字段名后面加_id """ class AuthorDetail(models.Model): phone = models.BigIntegerField() addr = models.CharField(max_length=32)
二 django生命周期
django路由层
一. 路由匹配机制
#urls.py文件: urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^$',views.home), url(r'^test/$',views.test), url(r'^testadd/$',views.testadd), url(r'',views.error) ] 1.第一个参数是正则表达式,匹配规则按照从上往下一次匹配,匹配到一个之后立即停止,直接执行对应的视图函数。 2.正是由于上面的特性 当你的项目特别庞大的时候 url的前后顺序也是你需要你考虑极有可能会出现url错乱的情况。 3.django在路由的匹配的时候 当你在浏览器中没有敲最后的斜杠,django会先拿着你没有敲斜杠的结果取匹配 如果都没有匹配上。会让浏览器在末尾加斜杠再发一次请求 再匹配一次 如果还匹配不上才会报错。 4.如果你想取消3的机制该不想做二次匹配可以在settings配置文件中配置加上一行代码: APPEND_SLASH = False # 该参数默认是True 5. 网站首页路由 url(r'^$',views.home) # views.home为视图函数,可根据实际情况更改 网站不存在页面 url(r'',views.error) # views.error为视图函数,可根据实际情况更改
二. 有名分组与无名分组(2者不能混合使用,都是将括号内匹配到的内容当做位置或关键字参数传递给视图函数)
#1.无名分组(路由匹配的时候 会将括号内正则表达式匹配到的内容 当做位置参数传递给视图函数)
#urls.py url(r'^test/(\d+)/',views.test), # 匹配一个或多个数字 # views.py def test(request,p): # p接收到匹配到的位置参数 print(p) return HttpResponse('test')
#2.有名分组(路由匹配的时候 会将括号内正则表达式匹配到的内容 当做关键字参数传递给视图函数)
#urls.py url(r'^test/(?P<year>\d+)/',views.test), # 匹配一个或多个数字 # views.py def test(request,year): # year接收匹配到的关键字参数,注意要与分组名一致 print(year) return HttpResponse('test')
#3.注意点
#1.无名分组和有名分组不能混着用!!! url(r'^test/(\d+)/(?P<year>\d+)/',views.test) # 报错 #2.但是用一种分组下 可以使用多个 # 无名分组支持多个 url(r'^test/(\d+)/(\d+)/', views.test), # 有名分组支持多个 url(r'^test/(?P<year>\d+)/(?P<xx>\d+)/', views.test),
三. 反向解析
作用:
1.a标签连接地址,可以根据url.py文件中路由改变而改变,类似于静态文件配置中的动态解析。
2.本质:根据名字动态获取到对应路径。
一般使用方式
1.先给url和视图函数对应关系起别名
url(路由(正则表达式),视图函数,name=别名) 例:这个名字能够唯一标识出对应的路径,不要重复 url(r'^index/$',views.index,name='kkk')
2.前后端反向解析
#前端 {% url '你给路由与视图函数对应关系起的别名' %} 例: <a href="{% url 'kkk' %}">1</a> #后端 reverse('你给路由与视图函数对应关系起的别名') 例: from django.shortcuts import render,HttpResponse,redirect,reverse def index(request): print(reverse('kkk') return HttpResponse('testadd')
有名分组和无名分组反向解析(与一般使用基本一样,只是路由加入了分组)
1.先给url和视图函数对应关系起别名
url(路由(正则表达式),视图函数,name=别名) 例:这个名字能够唯一标识出对应的路径,不要重复 url(r'^index/(?P<year>\d+)/$',views.index,name='kkk') # 这也可以是无名分组
2.前后端反向解析(有名无名都可)
#前端 {% url '别名' 数字 一般为id值 %} 例: <a href="{% url 'kkk' 1 %}">1</a> # 推荐你使用上面这种,有名无名都可,减少你的脑容量消耗 #<a href="{% url 'kkk' year=1 %}">1</a> # 有名分组专用,不推荐使用 #后端 reverse('你给路由与视图函数对应关系起的别名',args=(数字 一般为id值,)) 例: from django.shortcuts import render,HttpResponse,redirect,reverse def index(request,id): print(reverse('kkk',args=(id,))) # 推荐你使用上面这种,有名无名都可,减少你的脑容量消耗
url = reverse('kkk',args=(id,)
#print(reverse('kkk',kwargs={'year':1})) # 有名分组专用,不推荐使用
return HttpResponse('testadd')
3.总结
总结:针对有名分组与无名分组的反向解析统一采用一种格式即可 后端 reverse('list',args=(id,)) # 这里的数字通常都是数据的主键值 前端 {% url 'list' id %} # 这里的数字通常都是数据的主键值
四. 路由分发
1.django每一个app下面都可以有自己的urls.py路由层,templates文件夹,static文件夹,项目名下urls.py(总路由)不再做路由与视图函数的匹配关系而是做路由的分发。
2.路由分发,总路由相当于一个指路先锋。
使用:
1.项目总路由urls.py中配置(以2个应用app01和app02为例)
from django.conf.urls import url,include 方式1: 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)) ] 方式2: # 路由分发 注意路由分发总路由千万不要$结尾 urlpatterns = [ url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls')) ] # 将include()中的写成字符串就不需要导入2个app应用的urls.py了
2.各个应用下app的urls.py文件设置
#1.首先创建各个app的urls.py文件可直接拷贝总路由的在修改 #2.app01的urls.py文件 from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^index/',views.index) ] #3.app02的urls.py文件 from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^index/',views.index) ]
五. 名称空间
在路由分发情况下,多个app应用中的子路由和视图函数对应关系,起了相同的别名 这个时候用反向解析 并不会自动识别应用前缀,如果想避免这种问题的发生.
解决方案
方式1名称空间(操作总路由,子路由对应关系别名可以相同): 总路由 url(r'^app01/',include('app01.urls',namespace='app01')) url(r'^app02/',include('app02.urls',namespace='app02')) 后端解析的时候 reverse('app01:index') reverse('app02:index') 前端解析的时候 {% url 'app01:index' %} {% url 'app02:index' %} 方式2:子路由对应关系起别名的时候不要冲突即可 一般情况下在起别名的时候通常建议以应用名作为前缀 name = 'app01_index' name = 'app02_index'
六. 伪静态
静态网页:数据是写死的 万年不变
伪静态网页的设计是为了增加百度等搜索引擎seo查询力度
所有的搜索引擎其实都是一个巨大的爬虫程序
网站优化相关 通过伪静态确实可以提高你的网站被查询出来的概率
但是再怎么优化也抵不过RMB玩家
操作方法(在路由的正则表达式中加上 '.html')
url(r'^index.html',views.index,name='app01_index')
七.虚拟环境
1.一般情况下 我们会给每一个项目 配备该项目所需要的模块 不需要的一概不装
2.虚拟环境 就类似于为每个项目量身定做的解释器环境
3.每创建一个虚拟环境 就类似于你又下载了一个全新的python解释器
创建虚拟环境
#1.
#2.
#3.
八.django版本区别
django1.X跟django2.X版本区别: 1.路由层1.X用的是url,而2.X用的是path 2.2.X版本中的path第一个参数不再是正则表达式,而是(字符串)写什么就匹配什么 是精准匹配 3.当你使用2.X不习惯的时候 2.X还有一个叫re_path,2.x中的re_path就是你1.X的url 虽然2.X中path不支持正则表达式 但是它提供了五种默认的转换器 1.0版本的url和2.0版本的re_path分组出来的数据都是字符串类型 默认有五个转换器,感兴趣的自己可以课下去试一下 str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式 int,匹配正整数,包含0。 slug,匹配字母、数字以及横杠、下划线组成的字符串。 uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。 path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
补充:
value = 333
'%04d' % value 占四位,不够用0填满,超了则就按超了的位数来!