django链接MySQL ORM对象关系映射django对于数据库的字段以及数据的增删改查
# 1.配置文件中配置
DATABASES = 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'day60', 'USER':'root', 'PASSWORD':'123456', 'HOST':'127.0.0.1', 'PORT':3306, 'CHARSET':'utf8' } }
配置改了之后就起不来了,
django默认用的是mysqldb模块链接MySQL
但是该模块的兼容性不好 需要手动改为用pymysql链接
你需要告诉django不要用默认的mysqldb还是用pymysql
# 在项目名下的init或者任意的应用名下的init文件中书写以下代码都可以
init文件指定pymysql
import pymysql pymysql.install_as_MySQLdb()
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # 使用mysql数据库 'NAME': 'db1', # 要连接的数据库 'USER': 'root', # 链接数据库的用于名 'PASSWORD': '', # 链接数据库的用于名 'HOST': '127.0.0.1', # mysql服务监听的ip 'PORT': 3306, # mysql服务监听的端口 'ATOMIC_REQUEST': True, #设置为True代表同一个http请求所对应的所有sql都放在一个事务中执行 #(要么所有都成功,要么所有都失败),这是全局性的配置,如果要对某个 #http请求放水(然后自定义事务),可以用non_atomic_requests修饰器 'OPTIONS': { "init_command": "SET storage_engine=INNODB", #设置创建表的存储引擎为INNODB } } }
在链接mysql数据库前,必须事先创建好数据库
mysql> create database db1; # 数据库名必须与settings.py中指定的名字对应上
目前我们的django程序都是运行于python3.x解释器下,于是我们需要修改django的orm默认操作数据库的模块为pymysql,具体做法如下
ORM. 对象关系映射
作用:能够让一个不用sql语句的小白也能够通过python 面向对象的代码简单快捷的操作数据库
不足之处:封装程度太高 有时候sql语句的效率偏低 需要你自己写SQL语句
1 先去models.py中书写一个类
class User(models.Model): # id int primary_key auto_increment (MYSQL语句) id = models.AutoField(primary_key=True) # username varchar(32) username = models.CharField(max_length=32) # password int password = models.IntegerField()
2 数据库迁移命令
python3 manage.py makemigrations #将操作记录记录到小本本上(migrations文件夹)
python3 manage.py migrate #将操作真正的同步到数据库中
# 只要你修改了models.py中跟数据库相关的代码 就必须重新执行上述的两条命令
直接输:makemigrations和migrate
改
当表中有数据了 我想添加一个字段
①可以在终端内直接给出默认值,在迁移第一个命令后会返回存在的字段没默认值做不到,这时我们输入1,然后输入字段的值例如新字段是age,我们的值输入18,再继续迁移第二句即可
②该字段可以为空,之后再迁移
info = models.CharField(max_length=32,verbose_name='个人简介',null=True)
③直接给字段设置默认值,之后再迁移
hobby = models.CharField(max_length=32,verbose_name='兴趣爱好',default='study')
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()
如果想打印orm转换过程中的sql,需要在settings中进行配置日志:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
最后在命令行中执行两条数据库迁移命令,即可在指定的数据库db1中创建表 : $ python manage.py makemigrations $ python manage.py migrate # 注意: # 1、makemigrations只是生成一个数据库迁移记录的文件,而migrate才是将更改真正提交到数据库执行 # 2、数据库迁移记录的文件存放于app01下的migrations文件夹里 # 3、了解:使用命令python manage.py showmigrations可以查看没有执行migrate的文件
在表生成之后,如果需要增加、删除、修改表中字段,需要这么做 # 一:增加字段 #1.1、在模型类Employee里直接新增字段,强调:对于orm来说,新增的字段必须用default指定默认值 publish = models.CharField(max_length=12,default='人民出版社',null=True) #1.2、重新执行那两条数据库迁移命令 # 二:删除字段 #2.1 直接注释掉字段 #2.2 重新执行那两条数据库迁移命令 # 三:修改字段 #2.1 将模型类中字段修改 #2.2 重新执行那两条数据库迁移命令
""" 在操作models.py的时候一定要细心 千万不要注释一些字段 执行迁移命令之前最好先检查一下自己写的代码 """ 当你离开你的计算机之后一定要锁屏
def login(request): #返回登录界面 # print('来了 老弟') if request.method=='POST': username=request.POST.get('username') password=request.POST.get('password') # hobby=request.POST.getlist('hobby') user_obj=models.User.objects.filter(username=username).first() #查 返回值先看成是列表看数据的对象的格式,也支持索引取值,切片操作,但是不支持负数操作 #不推荐使用索引 推荐使用.first()
#user_obj = models.User.objects.filter(username=username).first()
#filter括号内可以携带多个参数 参数与参数之间默认是and关系
#你可以把filter联想成where记忆
# user_obj=res[0] # print(user_obj) # print(user_obj.username) # print(user_obj.password) if user_obj: if password == user_obj.password: return HttpResponse("登录成功") else: return HttpResponse("密码错误") return HttpResponse('用户不存在')
增
# 增 from app01 import models res = models.User.objects.create(username=username,password=password) # 返回值就是当前被创建的对象本身 # 第二种增加 user_obj = models.User(username=username,password=password) user_obj.save() # 保存数据
示例:先将数据库中的数据全部展示到前端 然后给每一个数据两个按钮一个编辑一个删除
查全部、改编辑修改
view:
def userlist(request): user_queryset=models.User.objects.all() #查全部 # return render(request,'userlist.html',{'user_queryset':user_queryset}) return render(request,'userlist.html',locals()) #这种会把当前所有的变量都通过locals()传到html,比较方便
def edit_user(request):
edit_id = request.GET.get('user_id')
# 获取url问号后面的参数
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查询出来的列表中所有的对象全部更新 批量更新操作
return redirect('/userlist/')
#跳转到数据的展示页面
edit_obj=models.User.objects.filter(id=edit_id).first()
return render(request,'edit_useer.html',locals())
编辑修改数据方式二:局部更新、单独更新 小缺点当字段特别多的时候效率会非常的低 因为是从头到尾将数据的所有字段更新一遍,修没修改都更新一遍
def edit_user(request):
edit_id = request.GET.get('user_id')
# 获取url问号后面的参数
edit_obj=models.User.objects.filter(id=edit_id).first()
# 查询当前用户想要编辑的数据对象
if request.method=='POST':
username=request.POST.get('username')
password=request.POST.get('password')
edit_obj.username=username
edit_obj.password=password
edit_obj.save()
return redirect('/userlist/')
#跳转到数据的展示页面
edit_obj=models.User.objects.filter(id=edit_id).first()
return render(request,'edit_useer.html',locals())
userlist.html:
如何告诉后端用户想要编辑哪条数据?
将编辑按钮所在的那一行数据的主键值发送给后端
利用url问号后面携带参数的方式

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> {% load static %} <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> <scrip src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></scrip> <title>Title</title> </head> <body> <h1 class="text-center">数据展示</h1> <div class="container"> <div class="row"> <div class="col-md-8 col-md-2"> <table> <tr> <th>ID</th> <th>username</th> <th>password</th> <th>action</th> </tr> </table> <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="" class="btn btn-primary btn-xs">编辑</a> <a href="" class="btn btn-danger btn-xs">删除</a> </td> </tr> {% endfor %} </tbody> </div> </div> </div> </body> </html>
edit_user.html:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> {% load static %} <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> <scrip src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></scrip> </head> <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="password" 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> </html>
urls.py:
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('index/',views.index), path('home/',views.home), path('login/',views.login), #登录功能 path('register/',views.reg), #注册功能 path('userlist/',views.userlist), #展示用户 path('edit_user/',views.edit_user),#编辑用户 path('delete_user/',views.delete),#删除用户 ]
增
#第一种
def reg(request):
if request.method=='POST':
username=request.POST.get('username')
password=request.POST.get('password')
res=models.User.objects.creat(username=username,password=password)
return render(request,'reg.html')
#第二种
def reg(request):
if request.method=='POST':
username=request.POST.get('username')
password=request.POST.get('password')
user_obj=models.User(username=username,password=password)
user_obj.save()
return render(request,'reg.html')
删除
views:
def delete(request): delete_id=request.GET.get('user_id') # 获取用户想要删除的数据id值 models.User.objects.filter(id=delete_id).delete()
#直接去数据库中找到对应的数据删除即可
#.delete()是一个批量删除 #跳转到展示页面
return redirect('/userlist/')
html:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> {% load static %} <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> <scrip src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></scrip> </head> <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="password" 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> </html>
真正的删除功能应该需要二次确认
删除数据内部其实并不是真正的删除 我们会给数据添加一个标识字段用来表示当前数据是否被删除了,
如果数据被删了仅仅只是讲字段修改一个状态,但是在硬盘里还是实实在在的存在
username password is_delete
jason 123 0
egon 123 1
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南