景泽元的编程 2020-01-06
一对多
多对多
一对一
利用换位思考的方式,分别站在两张表的角度上去思考
这里比如我们以图书管理系统为例来创建几个简单的表
图书表
出版社表
作者表
为了方便演示,这里我们就强行规定了表之间的关系:
图书和出版社是一对多的外键关系,一对多外键关系 将外键字段建在多的哪一张表上
图书与作者之间是多对多的外键关系,多对多的外键关系 外键字段无论建在那张表都可以,但是推荐你建在查询频率高的那张 表上
作者与作者与作者详情是一对一的外键关系,一对一 的外键关系外键字段建在那张表都可以,但是推荐你建在查询频率高的那 张表上
注意:
1、在书写表关系的时候,要先把基表全部写出来之后再考虑外键字段
2、Foreignkey字段以及OneToOneField字段 在创建表的时候orm都会自动给该字段加_id的后缀(无论你自己有没有加)
3、authors字段是一个虚拟的字段 并不会真正的在表中创建出来,只是用来告诉Django orm 需要创建一个第三方表
- 创建表的代码演示:
from django.db import models # Create your models here. class Book(models.Model): # id 是自动创建的 这里就不创建了 title = models.CharField(max_length=64) # price 为小数字段 这句话代表总共8位数小数位占2位 price = models.DecimalField(max_digits=8, decimal_places=2) # 书籍与出版社是一对多的关系 publish = models.ForeignKey(to=‘Publish‘) # 这句话的意思代表书籍表与出版社表关联,默认关联字段就是出版社的主键字段 # publish = models.ForeignKey(to=Publish) # 注意: to后面也可以直接书写表的变量名, 但是需要保证该变量名在当前位置的上方先定义 # 书籍与作者是对对多外键关系 authors = models.ManyToManyField(to=‘Author‘) # 书籍与作者是多对多关系 ‘‘‘ authors 字段是一个虚拟字段 不会真正的在表中创建出来,只是 用来告诉Django orm 需要创建书籍和作者的第三方关系表 ‘‘‘ class Publish(models.Model): name = models.CharField(max_length=64) addr = models.CharField(max_length=64) class Author(models.Model): name = models.CharField(max_length=32) phone = models.BigIntegerField() # 一对一外键关系建立 author_detail = models.OneToOneField(to=‘AuthorDetail‘) class AuthorDetail(models.Model): age = models.IntegerField() addr = models.CharField(max_length=255)
models.py
注: 这里我们演示使用的就是Django默认自带的sqlite3的数据库,同理在使用之前也应该类似于使用mysql一样,先去下载驱动文件
- url 方法
urlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘test‘,views.test), url(r‘testadd‘,views.testadd) ]url方法第一个参数是一个正则表达式,路由匹配按照正则表达式去匹配 一旦正则能够匹配到内容 会立刻执行对应的视图函数,就不会再继续匹配了注意:用户在浏览器中输入url时不加最后的斜杠 Django会默认自动加上,你可以在配置文件中指定是否开启该功能APPEND_SLASH = True/False
- url 参数中的几种演示
1、url第一个参数什么都不加
2、url第一个参数中加了一个/
分组就是给一段正则表达式加括号
在路由分配的时候给某段正则表达式加了括号,匹配的时候会将括号内正则表达式匹配到的内容当做位置参数传递给对应的视图函数
比如:无名分组
url(r‘^test/([0-9]{4})/‘,views.test) # 视图函数 def index(request,args): return HttpResponse(‘‘)
- 演示
有名分组就是给一段正则表达式起一个别名,在匹配的时候会将括号内正则表达式匹配到的内容当做关键字参数传递给对应的视图函数
比如:有名分组
url(r‘^test/(?P<year>\d+)/‘,views.test) # 视图函数 def index(request,year): ...- 演示
答:不能!!!
注:虽然两种命名方式不能混合使用,但同一种命名方式可以使用多次
- 演示
通过一些方法,就能够得到一个结果,该结果可以反向的去访问到对应的url
使用方法:
1、要先给路由与视图函数对应关系 起一个名字,比如:
url(r‘^testadd/‘, views.testadd, name=‘add‘)
2、前端解析
{% url ‘你起的绑定的名字‘ %}
3、后端解析
from django.shortcuts import render, HttpResponse, redirect
然后只需要给你的视图函数在reverse的参数中绑定你起的名字即可
reverse(‘add‘)
- 演示
1、路由与视图函数对应关系 起一个名字
2、前端解析
3、后端解析
1、无名分组反向解析
url(r‘^testadd/(\d+)/‘, views.testadd, name=‘add‘)
2、前端解析
{% url ‘你起的绑定的名字‘ 123 %}
3、后端解析
reverse(‘add‘, args=(12,))
- 演示
1、urls
2、前端解析
3、后端解析
1、有名分组反向解析
url(r‘^testadd/(?P<year>)(\d+)/‘, views.testadd, name=‘add‘)
2、前端解析
{% url ‘你起的绑定的名字‘ 123 %} #和无名使用方法一样,推荐使用
{% url ‘你起的绑定的名字‘ year=123 %} # 标准的
3、后端解析
reverse(‘add‘, args=(12,))
reverse(‘add‘, kwargs={‘year‘: 12}) # 标准写法
4、伪代码诠释
伪代码诠释""" url(r‘^edit_user/(\d+)/‘,views.edit_user,names=‘edit‘) {% for user_obj in user_queryset %} <a href="edit_user/{{ user_obj.id }}/">编辑</a> <a href="{% url ‘edit‘ user_obj.id %}">编辑</a> {% endfor %} def edit_user(request,edit_id): reverse(‘edit‘,args=(edit_id,)) """- 演示
当django项目比较庞大的时候 路由与视图函数对应关系较多 总路由代码太多冗长 考虑到总路由代码不好维护 django支持每个app都可以有自己的urls.py 并且总路由不再做路由与视图函数的对应关系 而仅仅只做一个分发任务的操作 根据请求的不同 识别出当前请求需要访问的功能属于哪个app然后自动 下发到对应app里面的urls.py中 然后由app里面的urls.py做路由与视图函数的匹配 不仅如此每个app除了可以有自己的urls.py之外 还可以有自己的static文件夹 templates模板文件 基于上面的特点 基于django分小组开发 会变得额外的简单 每个人只需要开发自己的app即可 之后只需要创建一个空的django项目 将多个人的app全部拷贝项目下 配置文件注册 总路由分发一次 需要一个分发的模块 1.总路由 from django.conf.urls import url,include # 路由分发 注意事项应用名后面千万不能加$ # from app01 import urls as app01_urls # from app02 import urls as app02_urls # url(r‘^app01/‘,include(app01_urls)), # url(r‘^app02/‘,include(app02_urls)) # 简写 url(r‘^app01/‘,include(‘app01.urls‘)), url(r‘^app02/‘,include(‘app02.urls‘)) 2.子路由 from django.conf.urls import url from app01 import views urlpatterns = [ url(r‘^index/‘,views.index) ] from django.conf.urls import url from app02 import views urlpatterns = [ url(r‘^index/‘,views.index) ]