django orm创建表关系

    1. 在学创建表关系之前,先复习表的之间的关系
    2. '''
    3. 表之间的关系
    4. 一对一
    5. 一对多
    6. 多对多
    7. 没关系
    8. '''
    9. 判断表关系的方法:换位思考
    10. '''
    11. 图书表
    12. 出版社表
    13. 作者表
    14. 作者详情表
    15. '''
    16. 表关系:
    17. 作者与图书:多对多 外键建在查询频率较高的一方
    18. 出版社与图书 一对多 外键建在多的一方
    19. 作者和作者详情 一对一外键建在查询频率较高的一方
    20. 这个时候来研究如何使用orm来创建表关系(我更推荐先建立好表,再去建立关系,大不了再重新刷进去,这样思路清晰一点)
    21. #不建立主键是因为有会自动创建主键
    22. class Book(models.Model):
    23. title = models.CharField(max_length=32)
    24. price = models.DecimalField(max_digits=8,decimal_places=2)
    25. publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE,)# 默认就是与出版社表的主键字段做外键关联
    26. """
    27. 如果字段对应的是ForeignKey 那么会orm会自动在字段的后面加_id
    28. 如果你自作聪明的加了_id那么orm还是会在后面继续加_id
    29. 后面在定义ForeignKey的时候就不要自己加_id
    30. """
    31. authors = models.ManyToManyField(to='Author')
    32. """
    33. authors是一个虚拟字段 主要是用来告诉orm 书籍表和作者表是多对多关系
    34. 让orm自动帮你创建第三张关系表
    35. """
    36. class Publish(models.Model):
    37. name = models.CharField(max_length=32)
    38. addr = models.CharField(max_length=32)
    39. class Author(models.Model):
    40. name = models.CharField(max_length=32)
    41. age = models.IntegerField()
    42. author_detail = models.OneToOneField(to='AuthorDetail',on_delete=models.CASCADE,)
    43. class AuthorDetail(models.Model):
    44. phone = models.CharField(max_length=32)
    45. addr = models.CharField(max_length=32)
    46. '''
    47. 在django 升级到2.0之后,表与表之间关联的时候,必须要写on_delete参数,否则会报异常:
    48. 定义外键的时候需要加上 on_delete=;
    49. 即:contract = models.ForeignKey(Contract, on_delete=models.CASCADE)
    50. 一对一,一对多都需要加,多对多就不需要
    51. '''
    52. """
    53. orm中如何定义三种关系
    54. publish = models.ForeignKey(to='Publish') # 默认就是与出版社表的主键字段做外键关联
    55. authors = models.ManyToManyField(to='Author')
    56. author_detail = models.OneToOneField(to='AuthorDetail')
    57. ForeignKey
    58. OneToOneField
    59. 会自动在字段后面加_id后缀
    60. """
    61. # 在django1.X版本中外键默认都是级联更新删除的
    62. # 多对多的表关系可以有好几种创建方式 这里暂且先介绍一种
    63. # 针对外键字段里面的其他参数 暂时不要考虑 如果感兴趣自己可以百度试试看

    django请求生命周期流程图
    image.png

    1. 流程讲解:
    2. 首先浏览器找web接口要信息,web接口就先去缓存空间里找,找到了就会返回给他,找不到就去找django内的中间件,中间件紧接着一层一层往里进,如果涉及到模板层和模型层就会去找他们要数据,没有就一般在视图层结束拿到信息以后,就原路返回一层一层反回去,到中间件直接返回给web接口,web接口返回给浏览器的同时,把这份信息丢进了缓存空间
    3. 找的过程:
    4. (有就直接返回) (有需要就会去找后面这俩)
    5. 浏览器--->web服务接口--->缓存空间--->中间件--->路由层--->视图层--->模板层
    6. --->模型层
    7. 返回的过程:
    8. 模板层--->视图层--->路由层--->中间件--->web服务接口--->浏览器
    9. 模型层---> --->缓存空间
    10. # 扩展知识点
    11. """
    12. 缓存数据库
    13. 提前已经将你想要的数据准备好了 你来直接拿就可以
    14. 提高效率和响应时间
    15. 当你在修改你的数据的时候 你会发现数据并不是立刻修改完成的
    16. 而是需要经过一段时间才会修改
    17. 博客园
    18. 了解即可
    19. """

    路由层
    路由匹配

    1. #路由匹配
    2. url(r'test',views.test),
    3. url(r'testadd',views.testadd)
    4. 1.x版本会存在正则匹配的情况,只要正则表达式匹配到内容就会立刻停止往下匹配,执行相应的视图函数,
    5. 意思就是我打http://127.0.0.1:8000/function/--->他还是会匹配test的视图函数
    6. 我用的django2.x已经解决了上述问题
    7. #如果你的urls设置的url带/而你在输入url的时候没有带斜杆那么django会自动给你再加一次斜杆匹配一次
    8. 比如path('function/',views.function),--->而我输入的是http://127.0.0.1:8000/function那么他就会自动进行重定向加斜杆再匹配一次
    9. # 取消自动加斜杠
    10. APPEND_SLASH = False/True # 默认是自动加斜杠的
    11. urlpatterns = [
    12. url(r'^admin/', admin.site.urls),
    13. # 首页
    14. url(r'^$',views.home),--->在django2.x版本以后是path 所以好像是取消了正则匹配
    15. # 路由匹配
    16. url(r'^test/$',views.test),
    17. url(r'^testadd/$',views.testadd),
    18. # 尾页(了解)
    19. url(r'',views.error),
    20. ]

    1.x 版本
    无名分组

    1. """
    2. 分组:就是给某一段正则表达式用小括号扩起来
    3. """
    4. url(r'^test/(\d+)/',views.test)
    5. def test(request,xx):
    6. print(xx)
    7. return HttpResponse('test')
    8. # 无名分组就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数

    有名分组

    1. """
    2. 分组:就是给某一段正则表达式用小括号扩起来
    3. """
    4. url(r'^test/(\d+)/',views.test)
    5. def test(request,xx):
    6. print(xx)
    7. return HttpResponse('test')
    8. # 无名分组就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数

    有名无名能否混合使用

    1. """
    2. 嘻嘻 不能混用
    3. 但是同一个分组可以使用N多次
    4. """
    5. # 单个的分组可以使用多次
    6. url(r'^index/(\d+)/(\d+)/(\d+)/',views.index),
    7. url(r'^index/(?P<year>\d+)/(?P<age>\d+)/(?P<month>\d+)/',views.index),

    2.x版本以后

    1. from django.urls import path, re_path
    2. # 向下兼容,不建议使用url, 使用与url相同的re_path
    3. from django.conf.urls import url
    4. urlpatterns = [
    5. path('index/', views.index),
    6. # page/<int:msg>/ page/(?P<msg>(\d+)) # 访问/page/123/
    7. # path('page/<int:msg>/', views.page),--->加:就是有名分组
    8. # path('page/<str>/', views.page),--->不加还是有名分组,不过名字为本身
    9. # path('page/<path:msg>/', views.page),
    10. # path('page/<slug:msg>/', views.page),
    11. path('page/<uuid:msg>/', views.page),
    12. ]
    13. # 1. 2.x版本re_path的使用方式同1.x版本url
    14. # 2. path写的是绝对字符串,请求地址必须与路由地址完全匹配
    15. # 3. path拥有五个转换器:
    16. -- str:匹配除路径分隔符(/)外的字符串,默认
    17. -- int:匹配自然数
    18. -- slug:匹配字母、数字、横杠及下划线组成的字符串
    19. -- uuid:匹配uuid形式的数据
    20. -- path:匹配任何字符串,包括路径分隔符(/)
    21. 且在2.x版本以后,不存在无名分组,所以不存在混用情况,可以添加不同匹配原则,但是必须按照顺序来
    22. path('<int><str>',views.home)--->那么必须先数字再字符--->http://127.0.0.1:8000/5654dsd

    反向解析

    1. # 通过一些方法得到一个结果 该结果可以直接访问对应的url触发视图函数
    2. path('dddsadasd/',views.ddd,name='ooo')
    3. 前端获取
    4. <a href="{% url 'ooo'%}">1</a>
    5. 后端获取的是viewsurl
    6. from django.shortcuts import reverse
    7. print(reverse('ooo'))

    作业

    1. """
    2. 必做题:
    3. 1.整理今日内容到博客
    4. 2.自己完成单表的增删改查功能(结合前端鼠标点点操作)
    5. 3.自己找几张表练习如何创建表与表之间的关系
    6. 选做题:
    7. 1.尝试着利用路由匹配和反向解析完成数据的编辑和删除功能
    8. 2.构思图书管理系统(后面会讲,自己先尝试着看看)
    9. """