Django-4:django模型层ORM-1

ORM-1

一、如何操作数据库

用户注册之后,用户名密码等关键信息需要保存,而这些数据就存储在数据库中。

传统的操作数据库方式无非就三种:

  • 一、接显示器本地登陆winserver或者linux系统,linux的话下一步就是mysql -u用户名 -p密码 -h主机,通过敲命令的方式进入、数据库,随后使用SQL语句进行增删改查等操作。
  • 二、利用Xshell等远程链接客户端,直接连接到mysql服务器,或者是连接到“跳板机/堡垒机”,随后在跳板机上使用mysql命令,来连接进数据库。
  • 三、在前面的方法之上,利用mysql font、Navicat等可视化软件连接到数据库,随后通过鼠标点点的方式来进行库和表的操作,无需SQL命令。

由此看来mysql font、Navicat等可视化软件,相对于传统的方式还是很好用的,毕竟一些简单的增删查改不需要再书写复杂的SQL语句。

而在我们当前的环境下,无需另外下载,pycharm自带这些功能。

另外:

  • 对于数据库的操作应该是由代码来执行的,总不可能说,有一个用户注册,那我们就赶紧在数据库的表中插一条数据吧。
  • 所以我们django项目也需要连接到数据库,随后借助ORM框架将SQL转换成类、对象、属性来使用,这样我们无需书写原生SQL,直接可以由python代码实现对数据库的操作。

1.1 pycharm链接数据库

pycharm可以充当很多款数据库软件的客户端,可通过在pycharm中进行配置,实现数据库的可视化。

一、MySQL服务器初始化 

  • MySQL服务器中,新建了一个名为Python的库,随后可以验证是否可以查询到该库

    create database Python character set utf8;
    GRANT ALL PRIVILEGES ON python.* TO 'pythoner '@'%' IDENTIFIED BY 'pythoner_of_password' WITH GRANT OPTION;
    flush privileges;
    '''
    1.创建了个Python库。
    2.创建了个用户名,可通过任意主机连接到Python库,操作库中所有表。
    	用户名:pythoner
    	密码:pythoner_of_password
    '''
    

二、pycharm安装驱动,链接MySQL

具体配置如下:

  • **第一步:**找到pycharm中链接数据库的工具
image-20210924165408616

​ 如果按照上述方法都没用,则安装插件,如果还不行就重装pycharm

image-20210924171726295
  • 第二步:选择对应数据库,如mysql、mariadb

image-20210924173110607

  • 第三步:如果有感叹号提示,那么说明需要先下载驱动
image-20210924173248194
  • 第四步:填写数据库信息,链接数据库。
image-20210924174804999
  • 第五步:当不显示数据库的所有库时,点击“…”选中。

    ​ 选中需要使用的库,在pycharm中展示的库,就是数据库服务器中的库。

image-20210928113007670

pycharm配置完成之后,可以作为快速查询数据库数据的一个工具,后面操作数据库都是用的代码(orm)。

1.1.1 附:安装驱动报错

现象:

  • 如下图,安装驱动时,报错下载失败。
image-20220901210207863

解决方案

  • 报错不是说这个链接的插件下载失败嘛,那我们可以自行下载,然后手动指定驱动位置。

第一步:

  • 先按照链接进行下载

    https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.25/mysql-connector-java-8.0.25.jar
    

第二步:

  • 手动指定驱动位置

    image-20220901210311304 image-20220901211928930

1.2 django链接数据库

django默认使用的是一个sqlite3轻量数据库,所以我们把配置文件中,数据库的部分进行更改即可。

  • django连接数据库,默认用的是mysqldb模块,但是该模块的兼容性不好,后续需要手动改为用pymysql模块。

    另外sqlite3这个小型数据库会有很多的一些BUG,所以尽量该用其他数据库。

第一步:

  • 修改django默认数据库。

    # 默认用的是sqkite3
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3', #改为mysql
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),  #注释掉
        }
    }
    

第二步:

  • 补充库名、登录用户、密码、IP端口等信息,格式为字典

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            #补充上基本信息
            'NAME': '库名',
            'USER':'登录用户',
            'PASSWORD':'密码',
            'HOST':'IP地址',
            'PORT':3306,
            'CHARSET':'utf8'
        }
    }
    
  
  > 'ENGINE': 'django.db.backends.mysql'
  >
  > - 如果使用的是mariadb数据库,这里依旧.mysql,不影响连接。



**第三步:**

- 代码声明

  ```python
  '''
  django连接数据库,默认用的是mysqldb模块,但是该模块的兼容性不好,需要手动改为用pymysql模块
  '''
  # 在项目名下的init,或者任意的应用名下的init文件中,书写以下代码即可。
  import pymysql
  pymysql.install_as_MySQLdb()

1.3 ORM初识

简单来说:

  • ORM的作用,就是可以让我们无需写原生SQL语句,就可以完成对数据库的各种操作,而且还省略了一些SQL优化的工作,提高了程序的开发效率

ORM:对象关系映射

  • 模板层models.py中,定义的类 ----> 等于数据库中的表。
  • 定义的对象 ----> 等于数据库中的每一行数据。
  • 定义的对象属性 ----> 等于数据库中表的字段。

ORM的一些简单操作会在本文章中第二章以后进行介绍,剩下的会在路由层的知识点全部介绍完毕之后,再做补充。

二、Django ORM创建表

本章节主要介绍ORM如何创建表,以及表的字段

2.1 创建表和字段

代码示例:

  • 应用app_01下的models.py文件

    from django.db import models
    
    # Create your models here.
    
    # 书写类,类就等于表,类中的对象等于字段,固定写法,继承models.Model
    class User(models.Model):
        id = models.AutoField(primary_key=True)
        username = models.CharField(max_length=32)
        password = models.IntegerField()
    

    这样,一个User表就定义好了(此时还没同步到数据库),同时这个表中有三个字段,分别是id、username、password。

    那么这三个字段都是用不同的方法,不同的属性来创建的,那么这些都代表什么意思呢?

2.1.1 字段的定义及属性

关于更多,请见。。。。

以2.1章节中的代码为例:

一、id字段

id字段:

id = models.AutoField(primary_key=True)
  • models.AutoField :表示创建的字段为自增字段
    • primary_key : 表示是否为主键,值为True表示设置主键

二、username字段

username字段:

username = models.CharField(max_length=32)
  • models.CharField : 表示创建的该字段,在插入数据时的数据类型必须为char。
    • CharField在调用时有一个必传参数max_length,不然会报错
    • max_length参数表示最多不超过多少char(字节)

三、password字段

password字段:

password = models.IntegerField()
  • models.IntegerField: 表示创建的该字段,在插入数据时的数据类型必须为int。

四、其他补充

补充

  • price = models.DecimalField(max_digits=8,decimal_places=2)
    

    DecimalField 多用于创建小数字段

    max_digits : 表示小数总共多少位

    decimal_places :表示小数点后占几位。

总结:

  • 常用的创建字段方式有四种,models.AutoField、models.CharField、models.IntegerField、DecimalField
  • 其中models.CharField必须设定最大是多少字节

字段的一些常用属性

补充:
    1.  verbose_name该参数用来对字段的解释,例如:
        id = models.AutoField(primary_key=True,verbose_name='主键')

    2.  由于一张表中必须要有一个主键字段,并且一般情况下都叫id字段,
    	所以orm当你不定义主键字段的时候,orm会自动创建一个名为id主键字段,
   		也就意味着,后续在创建模型表的时候如果主键字段名无特殊要求,就叫做id,那么主键字段可以省略不写。

  	3.	该字段可为空
      	null = True

  	4.	该字段的默认值
      	default = '默认值'

2.2 数据库迁移

同步到数据库,非常重要!!!

一、数据库迁移命令

  • python3 manage.py makemigrations  # 或  python manage.py makemigrations
    

    将操作记录记录到小本本上(migrations文件夹)

    image-20220901212629713

二、将操作同步到数据库中

  • python3 manage.py migrate  # 或  python manage.py migrate
    

    将操作真正的同步到数据库中

    image-20220901220603740

什么情况下需要使用该命令?

只要修改了models.py中,跟数据库相关的代码,就必须重新执行上述的两条命令

当前项目中,应用名为app_01,那么我们创建的表就为app_01_user,这么做有一个好处,可以防止重复。

  • 其他表的作用在后续章节会陆续补充
image-20210928165708517

三、ORM字段的增删改查

在二章节中,我们知道了如何创建表、定义表字段,以及如何同步到数据库,那么章节将详细介绍如何对表的字段,进行增删改。

3.1 增加字段

方法:

'''
1.直接增加,如:
'''
class 表名(models.Model):
	# 略
	字段 = models.IntegerField()
	# 略

试想一下,现在有一个表,字段有ORM自动创建的ID字段,以及我们模型层定义的name、age字段,并且还插入了一些数据。

如果此时添加一个字段为addr,那么会是什么情况呢?

idnameageaddr
1张三29
2李四37
  • 因为新增的addr字段,如果没有默认值或者允许为空,那么就会出现下列报错:

    image-20210928214617322

解决方法:

增加字段时,指定该字段可为空或设置默认值即可

  • 示例:

    # 传入参数
    null = True  # 允许为空
    default='默认值'  # 设置默认值
    
    info = models.CharField(max_length=32,verbose_name='个人简介',null=True)
    hobby = models.CharField(max_length=32,verbose_name='兴趣爱好',default='study')
    

3.2 删除字段

方法:

  • 非常简单粗暴,直接将模型层models.py中的字段代码注释掉,随后同步数据库即可

示例:

  • 注释掉不想要的字段

    class User(models.Model):
        username = models.CharField(max_length=30,verbose_name='用户名')
        age = models.IntegerField(verbose_name='年龄')
        # info = models.CharField(max_length=32, verbose_name='个人简介', null=True)
        hobby = models.CharField(max_length=32, verbose_name='兴趣爱好', default='study')
    
  • 执行数据同步命令

    python manage.py makemigrations
    python manage.py migrate
    

表内该字段对应的所有数据,会随着一并删除。

3.3 更改字段

方法:

  • 增加字段与删除字段相结合。
  • 先注释掉不需要的字段,随后再书写想要的字段
  • 这个过程中会造成数据丢失

四、ORM数据的增删改查

本章节将介绍如何通过ORM对数据进行增删改查

  • 依旧是暂时了解一点,后续补充连表查询F与Q查询等。

模板层负责建立与数据库之间的关系,所以获取、添加、修改、删除数据这些操作,都是要在视图层去完成操作的。

在查找视图层书写查询数据的代码时,第一步需要现将应用下的models.py作为模块导入到views.py文件。

# views.py文件
from 应用名 import  models

4.1 查找数据

格式:

  • # 全部取出
    models..objects.all()
    
    # 不写查询条件表示数据全部取出
    models..objects.filter()
    
    
    # 查询指定条件的数据
    models.User.objects.filter(username='张三')
    						# 这里的username数据库表中的字段名
        
    # filter可以有多个条件,逗号隔开,关系为and,也就是寻找条件都符合的。
    models.User.objects.filter(username='张三',id='2',password='123')
    

filter、all查询的返回值

  • 返回值为QuerySet对象(列表套字典的形式)

    <QuerySet [<User: User object>, <User: User object>]>
    
  • 改返回值中的的每个元素为用户对象,获取用户对象的方法:

    models.User.objects.filter(password=123)[0]
    models.User.objects.filter(password=123).first()
    '''
    此时会返回QuerySet对象中的第一个用户对象,即<User: User object>
    
    拿到用户对象后,可通过.字段名 的方式来获取该用户对象,存储在数据库中的值。
    
    不推荐使用索引的方式,推荐使用first()
    '''
    如:
    models.User.objects.filter(password=123)[0].username
    models.User.objects.filter(password=123,id=1).first().password
    

应用案例:登录验证

需求:

  • 登陆页面输入用户名和密码进行提交。
  • 后端将提交的数据进行校验,当用户名和密码均存在于数据库的同一条数据时,返回登陆成功
  • 如果输入的用户名和密码未在数据库中有记录,则返回用户名或密码错误
'''
1.判断用户的请求,为get请求返回login页面,为post请求则进行判断。
2.获取用户提交的信息。
3.获取数据库中的信息。
4.进行比对。
'''

def login(request):
    from app_01 import models

    if request.method == 'POST':   # 当请求为post时进行数据处理
        
		'''获取用户输入数据'''
        uname = request.POST.get('username')   # 此处的username为,前端input标签的name属性
        passwd = request.POST.get('password')  
        

        '''获取数据库中的数据'''
        res = models.User.objects.filter(username=uname)  #这里的username为表中的字段名     
        user_obj = res[0]
        # 这里推荐使用 res.first()
        # user_obj为数据对象,可通过 .字段 的方式获取数据,如:user_obj.password

     	'''进行数据对比'''
        if user_obj:
            if passwd == str(user_obj.password):    
             # 需要注意的是,用户在前端输入的内容为str,如果数据库中的密码字段为int,那么需要考虑数据类型的转换
                return HttpResponse('登录成功')
            else:
                return HttpResponse('密码错误')
        else:
            return  HttpResponse('用户不存在')   

    return render(request, 'login.html')     # 当用户为get请求时,返回login页面
4.1.1 补充:pk

当需要依据主键值进行查询时,可以使用“pk”来代指,这样不管主键是id还是uid还是userid,都可以使用"pk"表示。

models.User.objects.filter(pk=1)
'''
查询user表中,主键id值为1的数据。
'''

4.2 增加数据

格式:

  • from 应用名 import models
    models..objects.create(字段1='值',字段12='值', .....)
    

返回值:

  • create()会有返回值,返回值为创建的用户对象,4.1章节中的filter和all,用取出用户对象。
  • 有了用户对象之后,同样的可以通过**.sql字段名**的方式,获取数据,如:res.username,其中username为数据库中的字段名

第二种添加数据的方法:(了解即可)

user_obj = models.User(字段1='值',字段12='值', .....)  # 实例化对象,此时并没用到ORM
user_obj.save()  # 保存数据

应用案例:注册

路由层urls.py

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

urlpatterns = [
url(r'^admin/', admin.site.urls),
	
# 登陆
url(r'login/',views.login),

# 注册
url(r'register/',views.register),
]

视图层views.py

def register(request):
from app_01 import models

if request.method == 'POST':

'''获取表单输入的数据'''
uname = request.POST.get('Username') # 这里的Username是input表单name属性   
passwd = request.POST.get('Password') 

'''新建用户对象,并添加到数据库'''
res = models.User.objects.create(username=uname,password=passwd)   #这里的username为数据库的字段名。

return HttpResponse('注册成功,用户:'+res.username) # res.username获取刚刚用户数据对象的username字段值
					
return render(request, 'register.html')

模板层templates目录下的HTML文件

<!--register.html-->
<script src="/static_file/js/jquery.min.js"></script>
<script src="/static_file/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="/static_file/css/bootstrap.css">


<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h1 class="text-center">Register</h1>
<br>
<form class="form-horizontal" action=""  method="post">
{% csrf_token %}
  <div class="form-group">
    <label for="ipt_uname" class="col-sm-2 control-label">Uname</label>
    <div class="col-sm-10">
      <input type="text" class="form-control" id="ipt_uname" placeholder="Uname" name="uname">
    </div>
  </div>
  <div class="form-group">
    <label for="inputPassword3" class="col-sm-2 control-label">Password</label>
    <div class="col-sm-10">
      <input type="password" class="form-control" id="inputPassword3" placeholder="Password" name="upassword" >
    </div>
  </div>
    <div class="form-group">
    <div class="col-sm-offset-2 col-sm-10">
      <button type="submit" class="btn btn-success">Register</button>
    </div>
  </div>
</form>
</div>
</div>
</div>

最终效果展示:

django-orm-案例-1

4.3 修改与删除数据

修改/更新:

  • update()

    models.User.objects.filter(password='123').update(hobby='懒')
    # 将所有密码为123的数据对象,批量的把hobby字段值改为'懒'
    # 其中User为models.py中创建的表(类)
    

    返回值为影响的行数。

删除:

  • delete()

    models.User.objects.filter(id=9).delete()
    # 将id为9的数据删除
    

    返回值同样为受到影响的行数,如:(2, {‘app_01.User’: 2}) 意思就是2行收到delete操作的影响。

应用案例:编辑/删除用户列表

实现效果:

  • 通过点击**<编辑><删除>**这两个按钮,实现对后端数据库中的用户数据进行展示、更改、删除。
image-20210930144718488

思路:

	一、实现html页面展示数据。
		1.通过all()或者filter()获取数据库数据,拿到queryset对象。
		2.通过render(request,'xxx.html',locals()),将数据交给前端来使用。
		3.利用模板语法的for循环,循环得到数据对象,再用数据对象.方法 (方法名为数据库中的字段名) 的方式拿到后端数据


	二、实现编辑功能。
	'''
	实现编辑功能会遇到的问题1:
		数据有很多,用户可以点击第一条数据的编辑按钮,也可能会点击第三条数据的,那么我们怎么知道用户点击的是哪一行的
	'''
		解决方法:
		1.将编辑标签改为A标签,href属性为编辑HTML页面++参数的形式,参数为当前数据的ID值
        	如:<a href="/edit_user/?user_id={{ user_obj.id }}">编辑</a>
		2.之后用户点击按钮按钮时,会跳转到edit_user接口对应的视图函数,?问号后面的参数不参与路径匹配。
		3.随后在视图函数中利用request.GET 来获取跳转之前用编辑按钮所在行的ID字段值。
        4.拿到ID值之后,通过filter过滤,将需要被修改的数据展示在编辑页面,等待用户修改。

	'''
	实现编辑功能会遇到的问题2:
		用户在编辑页面上修改并提交之后,如何定位到数据库中的数据呢。
	'''
		解决办法:
		6.可以利用之前提取到的ID值
		7.之后通过update的方式进行修改。
		8.利用redirect,重定向到主页面。

	三、实现删除功能。
		9.逻辑同上,只不过不需要再单独创建一个html页面了。

演示效果:

django-orm-案例-2

源码

视图层views.py

'''
获取用户列表
'''
def get_userlist(request):
data_queryset = models.User.objects.all()
# 将queryset对象传递给html页面
return render(request,'userlist/userlist.html',locals())


'''
编辑用户信息
'''
def edit_userdata(request):
	# 获取需要修改的id
edit_userid = request.GET.get('user_id')
'''
编辑按钮会携带参数,参数为user_id=被修改数据的id
所以可以根据这个id来确定是哪个数据要进行修改
'''

# 当表单提交时,获取表单中的信息,随后更新数据
if request.method == 'POST':
ipt_name = request.POST.get('name')
ipt_age = request.POST.get('password')
ipt_hobby = request.POST.get('hobby')
# 批量更新
models.User.objects.filter(id=edit_userid).update(username=ipt_name,age=ipt_age,hobby=ipt_hobby)
		'''
		筛选出所有id等于edit_userid的数据,随后批量更新。
		'''
# 重定向,返回到首页列表
return redirect('/userlist/')
	
# 当表单为get请求时,将需要被修改的数据从数据取出,并渲染到页面上便于修改
edit_user_data = models.User.objects.filter(id=edit_userid).first()
return render(request,'userlist/edit_user.html',{'edit_user_data':edit_user_data})



'''
删除用户数据
'''
def dele_userdata(request):
edit_userid = request.GET.get('user_id')
models.User.objects.filter(id=edit_userid).delete()
return  redirect('/userlist/')


'''
添加用户数据
'''
def add_user(request):
if request.method == 'POST':
ipt_name = request.POST.get('name')
ipt_age = request.POST.get('password')
ipt_hobby = request.POST.get('hobby')
models.User.objects.create(username=ipt_name,age=ipt_age,hobby=ipt_hobby)
return  redirect('/userlist/')
return render(request,'userlist/add_user.html')

路由层urls.py

urlpatterns = [
url(r'^admin/', admin.site.urls),

url(r'userlist',views.get_userlist),
url(r'edit_user',views.edit_userdata),
url(r'delete_user',views.dele_userdata),
url(r'add_user',views.add_user),
]

模型层models.py

from django.db import models

# Create your models here.

class User(models.Model):
username = models.CharField(max_length=30,verbose_name='用户名')
age = models.IntegerField(verbose_name='年龄')
hobby = models.CharField(max_length=32, verbose_name='兴趣爱好')

注意要执行数据库同步命令

模板层

  • userlist.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/static_file/js/jquery.min.js"></script>
    <script src="/static_file/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="/static_file/css/bootstrap.css">
</head>
<body>

<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <h1 class="text-center">用户列表</h1>
            <br>
            <a href="/add_user/"><button class="btn btn-success btn-xs">新增数据</button></a>
             <table class="table table-striped table-hover">
                <thead>
                    <tr>
                        <th>UID</th>
                        <th>Username</th>
                        <th>Age</th>
                        <th>Hobby</th>
                        <th>Action</th>
                    </tr>
                </thead>

                <tbody>
                    {% for user_obj in data_queryset %}
                    <tr>
                        <td>{{ user_obj.id }}</td>
                        <td>{{ user_obj.username }}</td>
                        <td>{{ user_obj.age }}</td>
                        <td>{{ user_obj.hobby }}</td>
                        <td>
                            <a href="/edit_user/?user_id={{ user_obj.id }}" class="btn btn-primary btn-xs">编辑</a>
                            <a href="/delete_user/?user_id={{ user_obj.id }}" class="btn btn-danger btn-xs">删除</a>
                        </td>
                    </tr>
                    {% endfor %}
                </tbody>
            </table>

        </div>
    </div>
</div>
</body>
</html>
  • edit_user.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/static_file/js/jquery.min.js"></script>
    <script src="/static_file/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="/static_file/css/bootstrap.css">
</head>
<body>

<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <h1 class="text-center">编辑</h1>
            <br>
            <form class="form-horizontal" action=""  method="post">
            {% csrf_token %}
              <div class="form-group">
                <label for="ipt_uname" class="col-sm-2 control-label">Uname</label>
                <div class="col-sm-10">
                  <input type="text" class="form-control" id="ipt_uname" placeholder="姓名" name="name"  value="{{ edit_user_data.username }}">
                </div>
              </div>
              <div class="form-group">
                <label for="ipt_passwd" class="col-sm-2 control-label">Age</label>
                <div class="col-sm-10">
                  <input type="text" class="form-control" id="ipt_passwd" placeholder="年龄" name="password" value="{{ edit_user_data.age }}" >
                </div>
              </div>

               <div class="form-group">
                <label for="ipt_hobby" class="col-sm-2 control-label">Hobby</label>
                <div class="col-sm-10">
                  <input type="text" class="form-control" id="ipt_hobby" placeholder="爱好" name="hobby" value="{{ edit_user_data.hobby }}" >
                </div>
              </div>
                <div class="form-group">
                <div class="col-sm-offset-2 col-sm-10">
                  <button type="submit" class="btn btn-success">提交修改</button>
                </div>
              </div>
            </form>
        </div>
    </div>
</div>
</body>
</html>
  • add_user.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/static_file/js/jquery.min.js"></script>
    <script src="/static_file/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="/static_file/css/bootstrap.css">
</head>
<body>

<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <h1 class="text-center">添加</h1>
            <br>
            <form class="form-horizontal" action=""  method="post">
            {% csrf_token %}
              <div class="form-group">
                <label for="ipt_uname" class="col-sm-2 control-label">Uname</label>
                <div class="col-sm-10">
                  <input type="text" class="form-control" id="ipt_uname" placeholder="姓名" name="name">
                </div>
              </div>
              <div class="form-group">
                <label for="ipt_passwd" class="col-sm-2 control-label">Age</label>
                <div class="col-sm-10">
                  <input type="text" class="form-control" id="ipt_passwd" placeholder="年龄" name="password">
                </div>
              </div>
               <div class="form-group">
                <label for="ipt_hobby" class="col-sm-2 control-label">Hobby</label>
                <div class="col-sm-10">
                  <input type="text" class="form-control" id="ipt_hobby" placeholder="爱好" name="hobby">
                </div>
              </div>
                <div class="form-group">
                <div class="col-sm-offset-2 col-sm-10">
                  <button type="submit" class="btn btn-success">新增数据</button>
                </div>
              </div>
            </form>
        </div>
    </div>
</div>
</body>
</html>

五、ORM创建表关系

表与表之间的关系

  • 一对多
  • 多对多
  • 一对一
  • 没有关系
'''
以图书库为例:
	有 图书表、出版社表、作者表、作者详情表。
'''
1.其中,图书和出版社是一对多关系,外键字段建在多的那一方,也就是book表
	# 多个图书可以在同一家出版社出版,而同一本书因为版权不能再不同出版社出版,所以是“一对多”的关系。
    
2.图书和作者是多对多的关系,需要创建第三张表来专门存储,该表用来存储图书与作者的对应关系,类似于django路由。

3.作者与作者详情表是一对一

4.作者和出版社,没有关系,所以不需要建立表关系。

代码示例:

一、图书表与出版社表建立一对多关系,与作者表建立多对多关系

# 图书表
class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    # 总共八位 小数点后面占两位
    """图书和出版社是一对多,并且书是多的一方,所以外键字段放在书表里面。"""
    publish = models.ForeignKey(to='Publish')  # 默认是与出版社表的主键字段做外键关联


    """图书和作者是多对多的关系,外键字段建在任意一方均可,但是推荐建在查询频率较高的一方。
    	authors是一个虚拟字段,主要是用来告诉orm,书籍表和作者表是多对多关系,让orm自动帮你创建第三张关系表。
    	第三张关系表为  应用名_book_authors
    """
    authors = models.ManyToManyField(to='Author')
    



# 出版社表
class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)
  • 如果字段对应的是ForeignKey,那么orm会自动在字段的后面加_id,也就是book表中会多一个字段,名叫publish_id

    默认强制加的,如果字段名叫做publish_id,那么还是会加上_id后缀,就变成了publish_id_id

    所以,后面在定义ForeignKey的时候就不要自己加_id

二、作者与作者详情表建立一对一关系

class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    """
    作者与作者详情是一对一的关系,外键字段建在任意一方都可以,但是推荐建在查询频率较高的表中。
    """
    author_detail = models.OneToOneField(to='AuthorDetail')


class AuthorDetail(models.Model):
    phone = models.BigIntegerField()  # 或者直接字符类型
    addr = models.CharField(max_length=32)
  • 注:如果字段对应的是OneToOneField,那么会和ForeignKey一样,会自动在末尾添加_id后缀。

总结:

  • ORM中如何定义三种关系

    '''
    一对多
    '''
    models.ForeignKey(to='表名(类)')
    
    '''
    多对多
    '''
    res = models.ManyToManyField(to='表名(类)')
    # res为个虚拟字段,主要是用来告诉orm是多对多关系,需要它创建第三张关系表
    
    '''
    一对一
    '''
    models.OneToOneField(to='表名(类)')
    
    
    
    # 示例:
    publish = models.ForeignKey(to='Publish')   # 一对多	
    authors = models.ManyToManyField(to='Author')  # 多对多	
    author_detail = models.OneToOneField(to='AuthorDetail')  # 一对一
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿煜yv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值