首页 > 其他 > 详细

Django进阶2

时间:2020-05-26 22:44:16      阅读:62      评论:0      收藏:0      [点我收藏+]

Django ORM中创建表关系

"""
表与表之间的关系
    一对多
    
    多对多
    
    一对一
    
    没有关系

判断表关系的方法:换位思考
"""

我们以图书表,出版社表,作者表,以及作者详情表为例:

# 图书表  
# 出版社表
# 作者表
# 作者详情表

"""
图书和出版社是一对多的关系,外键字段建在多的一方,图书是多的一方
图书和作者是多对多的关系,要建一个中间表book2author记录图书和作者的关系
作者表和作者详情表是一对一
"""

Django连接数据库

settings.py,注释原有数据库配置

# 连接mysql数据库
DATABASES = {
    default: {
        ENGINE: django.db.backends.mysql,
        NAME: day61,    # name对应数据库的名字
        USER: root,
        PASSWORD: 123456,
        HOST: 127.0.0.1,
        PORT: 3306,
        CHARSET: utf8
    }
}

在项目或应用下的__init__.py中添加

import pymysql
pymysql.install_as_MySQLdb()

创建模型类:ps:django1.11.11中orm创建的外键字段默认就是级联更新、级联删除的

models.py

from django.db import models

# Create your models here.
# 创建表关系 先将基表创建出来,然后再添加外键字段

# 图书表
class Book(models.Model):
    title = models.CharField(max_length=32,verbose_name="图书名")
    price = models.DecimalField(max_digits=8,decimal_places=2,verbose_name="价格")
    # max_digits=8,decimal_places=2:小数总共八位,小数点后面占两位
    """
    图书和出版社是一对多关系,并且图书是多的一方,所以外键字段放在图书表里
    """
    publish = models.ForeignKey(to="Publish")          #一对多表关系  #publish是和Publish表关联的外键字段,默认是和Publish表的主键id字段关联,也可以使用to_field="id"指定

    """
    图书和作者是多对多关系,在ORM中不用手动创建中间表了,ORM会自动帮我们创建中间表,ORM中外键字段建在任意一方均可,但是推荐建在查询频率较高的一方
ps:
如果字段对应的是ForeignKey 那么orm会自动在字段后面加上_id后缀
如果你自己加上了_id那么orm还是会再自动在字段后面加上_id后缀
后面在定义ForeignKey的时候就不要自己加_id了
""" authors = models.ManyToManyField(to="Author") # 多对多表关系 """ authors 是一个虚拟字段,主要用来告诉ORM 图书表和作者表是多对多的关系 让ORM自动帮你创建第三方中间表 """ # 出版社 class Publish(models.Model): name = models.CharField(max_length=32,verbose_name="出版社名称") addr = models.CharField(max_length=32,verbose_name="出版社地址") # 作者 class Author(models.Model): name = models.CharField(max_length=32,verbose_name="姓名") age = models.IntegerField(verbose_name="年龄") """ 作者和作者详情是一对一关系,外键字段建在任意一方都可以,推荐建在查询频率较高的一方,这里外键建在作者表中 """ author_detail = models.OneToOneField(to="AuthorDetail") #一对一表关系
# OneToOneField也会自动给字段加_id后缀
#作者详情表 class AuthorDetail(models.Model): phone = models.BigIntegerField(verbose_name="手机号") addr = models.CharField(max_length=32,verbose_name="作者地址")

执行数据库迁移命令

# python3 manage.py makemigrations
# python3 manage.py migrate

查看数据库中的表

 技术分享图片

解释:

圈红圈的忽略:django自动创建的

app01_author:作者表

app01_authordetail:作者详情表

app01_book:图书表

技术分享图片
# 图书表
class Book(models.Model):
    title = models.CharField(max_length=32,verbose_name="图书名")
    price = models.DecimalField(max_digits=8,decimal_places=2,verbose_name="价格")
    # max_digits=8,decimal_places=2:小数总共八位,小数点后面占两位
    """
    图书和出版社是一对多关系,并且图书是多的一方,所以外键字段放在图书表里
    """
    publish = models.ForeignKey(to="Publish")          #一对多表关系  #publish是和Publish表关联的外键字段,默认是和Publish表的主键id字段关联,也可以使用to_field="id"指定

    """
    图书和作者是多对多关系,在ORM中不用手动创建中间表了,ORM会自动帮我们创建中间表,ORM中外键字段建在任意一方均可,但是推荐建在查询频率较高的一方
    """
    authors = models.ManyToManyField(to="Author")      # 多对多表关系
    """
    authors 是一个虚拟字段,主要用来告诉ORM 图书表和作者表是多对多的关系
    让ORM自动帮你创建第三方中间表
    """
图书表模型类代码

技术分享图片

 我们发现代码中加上id主键应该有五个字段(id、title、price、publish、authors)

但是在数据库表中只有(id、title、price、publish_id)

现在来解释:

为什么代码里写的外键名是publish,但是在数据库中是publish_id?

#ForeignKey   一对多外键
# OneToOneField  一对一外键
# 会自动在字段后面加_id后缀

为什么只有四个字段?

# 因为代码中authors是虚拟字段,主要用来告诉ORM 图书表和作者表是多对多的关系,让ORM自动帮你创建第三方中间表(就是多出来的表app01_book_authors)

app01_book_authors:这是django自动帮我们创建的图示表与作者表之间的中间表

app01_publish:出版社表

orm表与表关系创建总结

# orm中如何定义三种关系
    publish = models.ForeignKey(to=Publish)  # 一对多,默认就是与出版社表的主键字段做外键关联,也可以使用to_field="id"指定

    authors = models.ManyToManyField(to=Author)   # 多对多表关系
        
    author_detail = models.OneToOneField(to=AuthorDetail)   # 一对一表关系
        
# ps:        
    ForeignKey
    OneToOneField
    会自动在字段后面加_id后缀

补充:

# 在django1.X版本中外键默认都是级联更新删除的
# 多对多的表关系可以有好几种创建方式 这里暂且先介绍一种

Django请求周期流程图(必会)

技术分享图片

# 扩展知识点
    """
    缓存数据库
        提前已经将你想要的数据准备好了 你来直接拿就可以
        提高效率和响应时间
        
    当你在修改你的数据的时候 你会发现数据并不是立刻修改完成的
    而是需要经过一段时间才会修改
        博客园
    
    了解即可
    """

Django 每个部分详解

路由层

路由匹配

注意事项

1、惰性匹配

url(rtest,views.test),
url(rtestadd,views.testadd)
"""
url方法第一个参数是正则表达式
    只要第一个参数正则表达式能够匹配到内容 那么就会立刻停止往下匹配
    直接执行对应的视图函数
"""

示例:

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r^admin/, admin.site.urls),
    # 路由匹配
    url(rtest, views.test),
    url(rtestadd, views.testadd),
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

def test(request):

    return HttpResponse("test")

def testadd(request):

    return HttpResponse("testadd")

浏览器访问时,输入的包含test就可访问

技术分享图片

 2、自动加斜杠

url(rtest/, views.test),
url(rtestadd/, views.testadd),

"""
你在输入url的时候会默认加斜杠
    django内部帮你做到重定向
        一次匹配不行
        url后面加斜杠再来一次
"""

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r^admin/, admin.site.urls),
    # 路由匹配
    url(rtest/, views.test),
    url(rtestadd/, views.testadd),
]

views.py

技术分享图片
from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

def test(request):

    return HttpResponse("test")

def testadd(request):

    return HttpResponse("testadd")
views.py

浏览器输入:http://127.0.0.1:8000/testadd访问时

技术分享图片

你也可以在settings.py配置文件中取消django自动加斜杠/的机制

在settings.py中添加下面代码即可:

# 取消自动加斜杠
APPEND_SLASH = False    # True是开启

补充1:

url(rtest/, views.test),
url(rtestadd/, views.testadd),

浏览器输入http://127.0.0.1:8000/dfsjfdjksjtest/也能访问test,因为正则可以匹配

技术分享图片

 解决:加^匹配开头...

url(r^test/, views.test),
url(r^testadd/, views.testadd),

技术分享图片

 补充2、基于补充1

在浏览器输入http://127.0.0.1:8000/test/fafdsdfsfds还是能访问test

技术分享图片

 解决:加上$匹配结尾

url(r^test/$, views.test),
url(r^testadd/$, views.testadd),

技术分享图片

配置网站首页

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r^admin/, admin.site.urls),
    # 首页
    url(r^$,views.home),       # 推荐写法
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

# 首页
def home(request):
    return HttpResponse("home")

浏览器访问:http://127.0.0.1:8000/

技术分享图片

无名分组

"""
分组:就是给某一段正则表达式用小括号扩起来
"""

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r^admin/, admin.site.urls),
    # 首页
    url(r^$,views.home),
    # 分组
    url(r^test/(\d+), views.test),
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

# 首页
def home(request):
    return HttpResponse("home")

def test(request):

    return HttpResponse("test")

此时浏览器访问

技术分享图片

我们接收一下这个参数看看是什么

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

# 首页
def home(request):
    return HttpResponse("home")

def test(request,xxx):
    print(xxx)
    return HttpResponse("test")

此时浏览器访问:http://127.0.0.1:8000/test/123

技术分享图片

在后端查看打印信息:

技术分享图片

因此我们发现:

# 无名分组
    url(r^test/(\d+), views.test),    # 无名分组就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数

# 视图函数
def test(request,xx):
    print(xx)
    return HttpResponse(test)

有名分组

"""
可以给正则表达式起一个别名
"""

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r^admin/, admin.site.urls),
    # 首页
    url(r^$,views.home),
    # 无名分组
    url(r^test/(\d+), views.test),
    # 有名分组
    url(r^testadd/(?P<year>\d+), views.testadd),   # 给\d+这个表达式起了个别名year,这个year会传给视图函数testadd
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

# 首页
def home(request):
    return HttpResponse("home")

def test(request,xxx):
    print(xxx)
    return HttpResponse("test")

def testadd(request):

    return HttpResponse("testadd")

浏览器访问一下,看一下报错信息(testadd视图函数缺少一个关键字参数year)

技术分享图片

 我们给testadd视图函数加上year关键字参数year

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

# 首页
def home(request):
    return HttpResponse("home")

def test(request,xxx):
    print(xxx)
    return HttpResponse("test")

def testadd(request,year):
    print(year)
    return HttpResponse("testadd")

浏览器访问并在后端查看这个year关键字参数打印

技术分享图片

 技术分享图片

 因此我们发现:

url(r^testadd/(?P<year>\d+),views.testadd)    # 有名分组就是将括号内正则表达式匹配到的内容当作关键字参数传递给后面的视图函数

def testadd(request,year):
    print(year)
    return HttpResponse(testadd)

无名、有名分组是否可以混合使用

"""
两者不能混用
但是同一个分组可以使用N多次
"""

# 单个的分组可以使用多次
url(r^index/(\d+)/(\d+)/(\d+)/,views.index),
url(r^index/(?P<year>\d+)/(?P<age>\d+)/(?P<month>\d+)/,views.index),

反向解析

# 通过一些方法得到一个结果 该结果可以直接访问对应的url触发视图函数

# 先给路由与视图函数起一个别名
    url(r^func_kkk/,views.func,name=ooo)
# 反向解析
    # 后端反向解析
      from django.shortcuts import render,HttpResponse,redirect,reverse
      reverse(ooo)
  # 前端反向解析
      <a href="{% url ‘ooo‘ %}">111</a>

前端反向解析示例:

无论urls.py里面的匹配正则参数怎么改,通过home。html的a标签都能访问到func

urls.py

"""day61 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r‘^$‘, views.home, name=‘home‘)
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r‘^$‘, Home.as_view(), name=‘home‘)
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r‘^blog/‘, include(‘blog.urls‘))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r^admin/, admin.site.urls),
    # 首页
    url(r^$,views.home),
    # 无名分组
    url(r^test/(\d+), views.test),
    # 有名分组
    url(r^testadd/(?P<year>\d+), views.testadd),   # 给\d+这个表达式起了个别名year,这个year会传给视图函数testadd

    # 反向解析
    url(r^func, views.func,name="ooo")   # 先给路由与视图函数关系起一个别名
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

# 首页
def home(request):
    return render(request,"home.html")

def test(request,xxx):
    print(xxx)
    return HttpResponse("test")

def testadd(request,year):
    print(year)
    return HttpResponse("testadd")

# 反向解析
def func(request):

    return HttpResponse("func")

home.html

html文件通过模板语法{% url "urls.py中设置的别名" %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<a href="{% url "ooo" %}">111</a>
<a href="{% url "ooo" %}">222</a>
<a href="{% url "ooo" %}">333</a>
<a href="{% url "ooo" %}">444</a>
<a href="{% url "ooo" %}">555</a>
<a href="{% url "ooo" %}">666</a>
<a href="{% url "ooo" %}">777</a>
</body>
</html>

后端反向解析示例(views.py需要导入reverse)

from django.shortcuts import render,HttpResponse,redirect,reverse

# Create your views here.

# 首页
def home(request):
    # urls.py中的正则匹配怎么改这边都能通过别名接收到,注意要导入reverse模块
    print(reverse("ooo"))     # reverse("urls.py中设置的反向解析的名字")
    return render(request,"home.html")

 

Django进阶2

原文:https://www.cnblogs.com/baicai37/p/12968649.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!