ORM实现数据的增删改查和创建表关系
pycharm链接数据库(MySQL)
三个位置查找数据库
右侧上方database
左下方database
在配置文件的plugins插件搜索安装
没有的话卸载安装
在使用对应的数据库前,需要下载对应数据库的驱动
django链接数据库(MySQL)
# 默认用的是sqkite3 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } }
# 首先应当创建一个数据库(day60) 1、在配置文件中配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'day60', 'USER': 'root', 'PASSWORD': 'root', 'HOST': '127.0.0.1', 'PORT': 3306, 'CHARSET': 'utf8', } } 2、代码声明 django默认用的是mysqldb模块链接MySQL 但是该模块的兼容性不好 需要手动改为用pymysql链接 你需要告诉django不要用默认的mysqldb还是用pymysql # 在项目名下的init或者任意的应用名下的init文件中书写以下代码都可以 import pymysql pymysql.install_as_MySQLdb()
Django ORM
''' ORM 对象关系映射 作用:面向对象的代码能简单快捷的操作数据库 不足:封装程度太高,有时候sql语句的效率偏低,需要手动写sql语句 类 表 对象 记录 对象属性 记录某个字段对应的值 ''' # 在models.py中书写一个类 class User(models.Model): # id int primary_key auto_increment id = models.AutoField(primary_key=True) # username varchar(32) username = models.CharField(max_length=32) # password int password = models.IntegerField() ############数据库迁移命令########################################################################## python3 manage.py makemigrations 将操作记录记录到小本本上(migrations文件夹) 如果出现No changes detected的报错,则执行python3 manage.py makemigrations --empty App App是你的应用名 python3 manage.py migrate 将操作真正的同步到数据库中 # 只要你修改了models.py中跟数据库相关的代码 就必须重新执行上述的两条命令 ################################################################################################## class User(models.Model): # id int primary_key auto_increment id = models.AutoField(primary_key=True,verbose_name='主键') # username varchar(32) username = models.CharField(max_length=32,verbose_name='用户名') """ CharField必须要指定max_length参数 不指定会直接报错 verbose_name该参数是所有字段都有的 就是用来对字段的解释 """ # password int password = models.IntegerField(verbose_name='密码') class Author(models.Model): # 由于一张表中必须要有一个主键字段 并且一般情况下都叫id字段 # 所以orm当你不定义主键字段的时候 orm会自动帮你创建一个名为id主键字段 # 也就意味着 后续我们在创建模型表的时候如果主键字段名没有额外的叫法 那么主键字段可以省略不写 # username varchar(32) username = models.CharField(max_length=32) # password int password = models.IntegerField()
字段的增删改查
# 字段的增加 1.现在后端中加上你需要添加的字段,然后执行数据库迁移命令,可以在终端内直接给出默认值 2.该字段可以为空 info = models.CharField(max_length=32,verbose_name='个人简介',null=True) 3.直接给字段设置默认值 hobby = models.CharField(max_length=32,verbose_name='兴趣爱好',default='study') # 字段的修改 直接修改代码然后执行数据库迁移的两条命令即可! # 字段的删除 直接注释对应的字段然后执行数据库迁移的两条命令即可! 执行完毕之后字段对应的数据也都没有了
数据的增删改查
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class User(models.Model): id = models.AutoField(primary_key=True, verbose_name='主键',) username = models.CharField(max_length=32, verbose_name='用户名') password = models.IntegerField(verbose_name='密码')
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<body> <form action="" method="post"> <p>username: <input type="text" name="username"> </p> <p>password: <input type="text" name="password"> </p> <input type="submit" value="登录"> </form> </body>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<body> <form action="" method="post"> <p>username: <input type="text" name="username"> </p> <p>password: <input type="text" name="password"> </p> <input type="submit" value="注册"> </form> </body>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<body> <h1 class="text-center">数据展示</h1> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <table class="table table-striped table-hover"> <thead> <tr> <th>ID</th> <th>username</th> <th>password</th> <th>action</th> </tr> </thead> <tbody> {% for user_obj in user_queryset %} <tr> <td>{{ user_obj.id }}</td> <td>{{ user_obj.username }}</td> <td>{{ user_obj.password }}</td> <td> <a href="/app01/edit_user/?user_id={{ user_obj.id }}" class="btn btn-primary btn-xs">编辑</a> <a href="/app01/delete_user/?user_id={{ user_obj.id }}" class="btn btn-danger btn-xs">删除</a> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </body>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<body> <h1 class="text-center">编辑</h1> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <form action="" method="post"> <p>username:<input type="text" name="username" class="form-control" value="{{ edit_obj.username }}"></p> <p>password:<input type="text" name="password" class="form-control" value="{{ edit_obj.password }}"></p> <input type="submit" class="btn btn-info btn-block" value="编辑"> </form> </div> </div> </div> </body>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.urls import re_path from app01 import views urlpatterns = [ # 数据的查询 re_path(r'^look_user/', views.look_user), # 数据的增加 re_path(r'^add_user/',views.add_user), # 展示所有数据到前端 re_path(r'^user_list/', views.user_list), # 编辑功能 re_path(r'^edit_user/', views.edit_user), # 删除功能 re_path(r'^delete_user/',views.delete_user), ]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.shortcuts import render, HttpResponse, redirect from app01 import models def look_user(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') from app01 import models res = models.User.objects.filter(username=username) print(res) user_obj = res[0] print(user_obj) print(user_obj.username) # if models.User.objects.filter(username=username,password=password): # return HttpResponse('登入成功') # else: # return HttpResponse('输入错误') return render(request,'index.html') def add_user(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') if models.User.objects.filter(username=username): return HttpResponse('用户已经存在') else: res = models.User.objects.create(username=username,password=password) print(res) return HttpResponse('注册成功') return render(request,'reg.html') def user_list(request): # 查询出用户表里面的所有数据 user_queryset = models.User.objects.filter().all() return render(request, 'user_list.html', locals()) # 后端查询出用户想要编辑的数据对象,展示到前端页面供用户查看和编辑 def edit_user(request): # 获取url问号后面的参数 edit_id = request.GET.get('user_id') # 查询当前用户想要编辑的数据对象 edit_obj = models.User.objects.filter(id=edit_id).first() if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') # 去数据库中修改对应的数据内容 # 修改数据方式1 # models.User.objects.filter(id=edit_id).update(username=username,password=password) '''将filter查询出来的列表中所有的对象全部更新,批量操作,只修改被修改的字段''' # 修改数据方式2 edit_obj.username = username edit_obj.password = password edit_obj.save() '''当字段特别多的时候效率非常低,从头到尾将数据的所有字段全部更新一遍,无论该字段是否被修改''' # 跳转到数据的展示页面 return redirect('/app01/user_list/') # 将数据对象展示到页面上 return render(request,'edit_user.html',locals()) def delete_user(request): # 获取用户想要删除的数据的id值 delete_id = request.GET.get('user_id') # 直接到数据库中找到对应的数据删除 models.User.objects.filter(id=delete_id).delete() # 跳转到展示页面 return redirect('/app01/user_list') # 真正的删除功能应该需要二次确认 # 删除数据内部其实并不是真正的删除,程序员会给数据添加一个标识字段用来表示当前数据是否被删除,如果数据删除了仅仅只是将字段修改一个状态
查
# from app01 import models res = models.User.objects.filter(username=username) print(res) # <QuerySet [<User: User object (3)>]> ''' 返回值可看成列表套数据对象的格式 返回值支持索引取值,切片操作,但不支持负数索引 但是不推荐使用索引的方式取值 user_obj = models.User.objects.filter(username=username).first() filter括号内可携带多个参数,参数与参数之间默认是and关系 ''' user_obj = res[0] print(user_obj) # User object (3) print(user_obj.username) # 从form表单内输入的username的值 print(user_obj.password) # 从form表单内输入的password的值 # 查询出表中的所有数据的两种方式 models.User.objects.filter() models.user.objects.filter().all()
增
# from app01 import models # 第一种方法 res = models.User.object.create(username=username,password=password) # 返回值就是当前被创建的对象本身 User object (5) # 第二种方法 user_obj = models.User(username=username,password=password) user_obj.save() # 保存数据
改
# 修改数据方式1 # models.User.objects.filter(id=edit_id).update(username=username,password=password) '''将filter查询出来的列表中所有的对象全部更新,批量操作,只修改被修改的字段''' # 修改数据方式2 edit_obj.username = username edit_obj.password = password edit_obj.save() '''当字段特别多的时候效率非常低,从头到尾将数据的所有字段全部更新一遍,无论该字段是否被修改'''
删
models.User.objects.filter(id=delete_id).delete() # 真正的删除功能应该需要二次确认 我们这里先不做后面会讲 # 删除数据内部其实并不是真正的删除 我们会给数据添加一个标识字段用来表示当前数据是否被删除了,如果数据被删了仅仅只是讲字段修改一个状态 username password is_delete yuan 123 0 chen 456 1
图书表 出版社表 作者表 作者详情表 """ 图书和出版社是一对多的关系 外键字段建在多的那一方 book 图书和作者是多对多的关系 需要创建第三张表来专门存储 作者与作者详情表是一对一 """ from django.db import models # Create your models here. # 创建表关系 先将基表创建出来 然后再添加外键字段 class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8,decimal_places=2) # 总共八位 小数点后面占两位 """ 图书和出版社是一对多 并且书是多的一方 所以外键字段放在书表里面 """ publish = models.ForeignKey(to='Publish') # 默认就是与出版社表的主键字段做外键关联 """ 如果字段对应的是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) 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') """ OneToOneField也会自动给字段加_id后缀 所以你也不要自作聪明的自己加_id """ class AuthorDetail(models.Model): phone = models.BigIntegerField() # 或者直接字符类型 addr = models.CharField(max_length=32) """ orm中如何定义三种关系 publish = models.ForeignKey(to='Publish') # 默认就是与出版社表的主键字段做外键关联 authors = models.ManyToManyField(to='Author') author_detail = models.OneToOneField(to='AuthorDetail') ForeignKey OneToOneField 会自动在字段后面加_id后缀 """ # 在django1.X版本中外键默认都是级联更新删除的 # 多对多的表关系可以有好几种创建方式 这里暂且先介绍一种 # 针对外键字段里面的其他参数 暂时不要考虑 如果感兴趣自己可以百度试试看 # django2.0后,定义外键(一对多关系)和一对一关系的时候需要加on_delete选项
多表操作
一对多外键增删改查
# 一对多外键增删改 # 增 # 1 直接写实际字段 id # models.Book.objects.create(title='论语',price=899.23,publish_id=1) # models.Book.objects.create(title='聊斋',price=444.23,publish_id=2) # models.Book.objects.create(title='老子',price=333.66,publish_id=1) # 2 虚拟字段 对象 # publish_obj = models.Publish.objects.filter(pk=2).first() # models.Book.objects.create(title='红楼梦',price=666.23,publish=publish_obj) # 删 # models.Publish.objects.filter(pk=1).delete() # 级联删除 # 修改 # models.Book.objects.filter(pk=1).update(publish_id=2) # publish_obj = models.Publish.objects.filter(pk=1).first() # models.Book.objects.filter(pk=1).update(publish=publish_obj)
多对多外键增删改查
# 如何给书籍添加作者? book_obj = models.Book.objects.filter(pk=1).first() # print(book_obj.authors) # 就类似于你已经到了第三张关系表了 # book_obj.authors.add(1) # 书籍id为1的书籍绑定一个主键为1 的作者 # book_obj.authors.add(2,3) # author_obj = models.Author.objects.filter(pk=1).first() # author_obj1 = models.Author.objects.filter(pk=2).first() # author_obj2 = models.Author.objects.filter(pk=3).first() # book_obj.authors.add(author_obj) # book_obj.authors.add(author_obj1,author_obj2) """ add给第三张关系表添加数据 括号内既可以传数字也可以传对象 并且都支持多个 """ # 删 # book_obj.authors.remove(2) # book_obj.authors.remove(1,3) # author_obj = models.Author.objects.filter(pk=2).first() # author_obj1 = models.Author.objects.filter(pk=3).first() # book_obj.authors.remove(author_obj,author_obj1) """ remove 括号内既可以传数字也可以传对象 并且都支持多个 """ # 修改 # book_obj.authors.set([1,2]) # 括号内必须给一个可迭代对象 # book_obj.authors.set([3]) # 括号内必须给一个可迭代对象 # author_obj = models.Author.objects.filter(pk=2).first() # author_obj1 = models.Author.objects.filter(pk=3).first() # book_obj.authors.set([author_obj,author_obj1]) # 括号内必须给一个可迭代对象 """ set 括号内必须传一个可迭代对象,该对象内既可以数字也可以对象 并且都支持多个 """ # 清空 # 在第三张关系表中清空某个书籍与作者的绑定关系 book_obj.authors.clear() """ clear 括号内不要加任何参数 """