当前位置: 代码网 > it编程>数据库>Mysql > Django如何通过orm操作mysql

Django如何通过orm操作mysql

2026年07月17日 Mysql 我要评论
1、django简介django是用python语言写的开源web开发框架,并遵循mvc设计。对比flask框架,django原生提供了众多的功能组件,让开发更简便快速。采用mvc程序设计模式,其核心

1、django简介

django是用python语言写的开源web开发框架,并遵循mvc设计。对比flask框架,django原生提供了众多的功能组件,让开发更简便快速。

采用mvc程序设计模式,其核心思想是分工、解耦,让不同的代码块之间降低耦合,增强代码的可扩展性和可移植性,实现向后兼容。

数据库支持orm,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量。

2、mysql连接设置

在settings.py中保存了数据库的连接配置信息,django默认初始配置使用sqlite数据库。

# databases = {
#     'default': {
#         'engine': 'django.db.backends.sqlite3',
#         'name': os.path.join(base_dir, 'db.sqlite3'),
#     }
# }
databases = {
    'default': {
        'engine': 'django.db.backends.mysql',
        'name': "orm",  # 数据库提前创建好
        "host":"127.0.0.1",
        "port":3306,
        "user":"root",
        "password":"123456"
    }
}

让django的orm能以mysqldb的方式来调用pymysql,使用mysql数据库首先需要安装驱动程序

pip install pymysql

在django的工程目录的__init__.py中添加如下语句:

import pymysql
pymysql.install_as_mysqldb()

3、模型类字段和参数类型

字段类型

类型说明
autofield自增字段
charfield字符串,参数max_length表示最大字符数
textfield大文本字段
integerfield整数
decimafield十进制浮点数,参数max_digits表示总位数,不包括符号,参数decimal_places表示小数位数
floatfield浮点数
datefield日期, 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false; 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false; 参数auto_now_add和auto_now是相互排斥的,组合将会发生错误
timefield时间
datetimefield日期时间
filefield文件字段
booleanfield布尔字段
imagefield继承于filefield,对上传的内容进行校验,确保是有效的图片
foreignkey外键
onetoonefield一对多
manytomanyfield多对多

参数:

参数说明
null表示是否允许为空,默认为false
blank在表单中该字段是否允许为空,默认为false
db_index是否创建为索引,默认为false
db_column自定义字段名称
default默认值
primary_key若为true,则该字段设置为主键字段,一般和autofield搭配
unique唯一值,默认false
verbose_name指定在admin管理界面中显示中文;verbose_name表示单数形式的显示,verbose_name_plural表示复数形式的显示
choices二元组组成的一个可迭代对象,用来给字段提供选择项
auto_now_add创建数据记录的时候会把当前时间添加到数据库,默认为fasle
auto_now每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间,默认为false
on_delete在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理:cascade级联,删除主表数据时连通一起删除外键表中数据;protect保护,通过抛出protectederror异常,来阻止删除主表中被外键应用的数据;set_null设置为null,仅在该字段null=true允许为null时可用;set_default设置为默认值,仅在该字段设置了默认值时可用set()设置为特定值或者调用特定方法;do_nothing不做任何操作,如果数据库前置指明级联性,此选项会抛出integrityerror异常
foreignkey中参数to:设置要关联的表;to_field:设置要关联的表的字段;related_name:反向操作时,使用的字段名,用于代替原反向查询时的’表名_set’;related_query_name:反向查询操作时,使用的连接前缀,用于替换表名;on_delete;当删除关联表中的数据时,当前表与其关联的行的行为。
foreignkey的db_contraint只有关联关系,没有强制的约束关系
元信息(metadb_table:orm在数据库中的表名,默认是 app_类名。index_together:联合索引。unique_together:联合唯一索引。ordering:指定默认按什么字段排序。

4、orm

4.1、先建模型类,在迁移数据库

创建模型类,在models.py

from django.db import models

class teacher(models.model):

    id = models.autofield(primary_key=true,verbose_name="教师id")
    name = models.charfield(max_length=4,null=false,verbose_name="教师名称")
    age = models.integerfield(default=40,verbose_name="教师年龄")
    gender_list = ((1,"男"),(2,"女"),(3,"其他"))
    gender = models.integerfield(default=1,choices=gender_list,verbose_name="性别")
    phone = models.charfield(max_length=11,null=false,verbose_name="手机号")

    class meta:
        db_table = "teacher"
        verbose_name = "教师表"
        verbose_name_plural = verbose_name

#教师表和课程一对一的关系
class course(models.model):

    id = models.autofield(primary_key=true,verbose_name="课程id")
    name = models.charfield(max_length=16,null=false,verbose_name="课程名称")
    teacher = models.onetoonefield(to="teacher",to_field="id",on_delete=models.cascade,related_name="course")

    class meta:
        db_table = "course"
        verbose_name = "课程表"
        verbose_name_plural = verbose_name
#学生表和课程表是多对多关系
class student(models.model):

    id = models.autofield(primary_key=true)
    name = models.charfield(max_length=4,null=false,verbose_name="学生姓名")
    age = models.integerfield(default=20,verbose_name="年龄")
    gender_list = ((1,"男"),(2,"女"),(3,"其他"))
    gender = models.integerfield(choices=gender_list,default=1,verbose_name="性别")
    phone = models.charfield(max_length=11,null=false,verbose_name="手机号")
    course = models.manytomanyfield(to="course",through="studentcourse",through_fields=("student_id","course_id"),related_name="student")

    class meta:
        db_table = "student"
        verbose_name = "学生表"
        verbose_name_plural = verbose_name

    def __str__(self):
        return f"{self.id}:{self.name}"
#学生表和课程表的中间表
class studentcourse(models.model):

    id = models.autofield(primary_key=true)
    student_id = models.foreignkey(to="student",verbose_name="学生id")
    course_id = models.foreignkey(to = "course",verbose_name="课程id")

    class meta:
        db_table = "student_course"
        unique_together = ("student_id","course_id")
# 分数表和课程表、学生表是一对多关系
class grade(models.model):

    id = models.autofield(primary_key=true,verbose_name="分数id")
    score = models.decimalfield(default=0,decimal_places=1,max_digits=4,null=false,verbose_name="分数")
    student_id = models.foreignkey(to="student",to_field="id",on_delete=models.cascade,related_name="grade")
    course_id = models.foreignkey(to="course",to_field="id",on_delete=models.cascade,related_name="grade")

    class meta:
        db_table = "grade"
        verbose_name = "分数表"
        verbose_name_plural = verbose_name

迁移

# 终端上输入
#生成迁移文件
python manage.py makemigrations
#同步到数据库中
python manage.py migrate

4.2、先建数据库,在建模型类

在mysql中创建表,然后再models.py上创建模型类

create table student(
    id int primary key auto_increment comment "学生id",
    sname varchar(4) not null comment "姓名",
    gender enum("男","女") default "男" comment "性别",
    phone char(11) not null comment "手机号"
) engine="innodb",charset="utf8",comment="学生表";
create table teacher(
    id int primary key auto_increment comment "老师id",
    tname varchar(4) not null comment "老师姓名",
    gender enum("男","女") default "男" comment "性别",
    phone char(11) not null comment "手机号"
) engine="innodb" default charset=utf8 comment="教师表";
create table course(
    id int primary  key auto_increment comment "课程id",
    cname varchar(10) not null comment "课程名",
    teacher int default null comment "老师id",
    constraint c_t_key foreign key(teacher) references teacher(id)
) engine="innodb" default charset=utf8 comment="课程表";
create table grade(
    id int primary key auto_increment comment "分数id",
    score float default 0 comment "分数",
    student int default null comment "学生id",
    course int default null comment "课程id",
    constraint g_s_key foreign key(student) references student(id),
    constraint g_c_key foreign key(course) references course(id)
) engine="innodb" default charset=utf8 comment "分数表";
create table student_course(
    id int primary  key auto_increment comment "学生课程id",
    sid int default null comment "学生id",
    cid int default null comment "课程id",
    constraint s_s_c foreign key(sid) references student(id),
    constraint c_s_c foreign key(cid) references course(id)
) engine="innodb" default charset=utf8 comment="学生课程表";

5、数据库操作

5.1、增

单表添加

# obj.save()单个增加
student = models.student(name = "张三",gender=1,phone="12345678910")
student.save()
#create()新增---常用
student = models.student.objects.create(name = "李四",gender=2,phone="12345678911")
#bulk_create(list)批量增加
students = []
names = ["王五","李六","刘七"]
for i,name in enumerate(names,2):
    stu = models.student(name = name,gender=1,phone="1234567891" + str(i))
    students.append(stu)
stus = models.student.objects.bulk_create(students)

一对一、一对多、多对多添加

teachers = models.teacher.objects.all()
courses=["语文","数学","英语"]
for i,teacher in enumerate(teacher,1):
    #根据数据库中字段名赋值
    # course = models.course.objects.create(name=courses[i],teacher_id=teacher.id)
    #直接传对象
    course = models.course.objects.create(name=courses[i], teacher=teacher)

5.2、查

5.2.1、单表查询

#返回与所给筛选条件相匹配的对象,返回结果有且只有一个,多个会报错
student = models.student.objects.get(id=1)
#查询表所有结果
student_query = models.student.objects.all()
# 返回第一个数据对象
student_first = models.student.objects.first()
#返回第二个数据对象
student_last = models.student.objects.last()
#查询除了id为1的学生,类型为queryset
students = models.student.objects.exclude(id=1)
#判断是否包含数据
student = models.student.objects.all().exists()
#  返回查询结果的个数
count = models.student.objects.all().count()
#  对values返回结果中剔除重复纪录
students = models.student.objects.all().values("id","name").distinct()
#查询指定字段,queryset里包含字典
students = models.student.objects.filter(gender=1).values("id","name")
# queryset里包含元组
students = models.student.objects.filter(gender=1).values_list("id", "name")
#聚合:count,sum,avg,max,min,返回queryset列表
#from django.db.models import count,max,min,sum,avg
student = models.student.objects.values('gender').annotate(gid=count('gender'))
# 永远sql语句
student = models.student.objects.raw("select * from student")
# 聚合函数,获取字典类型聚合结果  {'gender_c': 2, 'id_c': 5}按性别分由两组,学生id分有5组
student = models.student.objects.aggregate(gender_c=count('gender', distinct=true), id_c=count('id'))
# 基于双下划线的模糊查询
student = models.student.objects.filter(gender__in=[1,2,3])
# 大于
student = models.student.objects.filter(age__lt=20)
# 小于
student = models.student.objects.filter(age__gt=20)
# 大于或等于
student = models.student.objects.filter(age__gte=20)
# 开头匹配
student = models.student.objects.filter(phone__startswith="123")
#模糊查询
student = models.student.objects.filter(name__contains="张").values("name")
#判断是否为空
student = models.student.objects.filter(name__isnull=true)
#排序
#升序
student = models.student.objects.order_by("age")
#降序
student = models.student.objects.order_by("-age")

5.2.2、多表联合查询

#正向查询(按字段:课程表的teacher):关联属性字段所在的表查询被关联表的记录就是正向查询,反之就是反向查询

#一对一或者一对多
course = models.course.objects.first()
teacher = course.teacher # ---对象
#反向查询(按表名course_set或者通过设置related_name=“course”代替'表名_set'。,因为加上_set是因为反向查询的时候,你查询出来的可能是多条记录的集合):
teacher = models.teacher.objects.first()
# 得到queryset类型数据
course = teacher.course_set.all()    或
course = teacher.course.all()
# 多对多,正向反向返回都是queryset类型
#正向
student = models.student.objects.first()
courses = student.course.all()
#反向
course = models.course.objects.first()
students = course.student_set.all()    或
students = course.student.all()

5.2.3、基于双下划线的跨表查询(基于join实现的)

# 一对一、一对多、多对多方法都一样
# 正向
grade = models.grade.objects.filter(student_id__name="张三").values("score")
# 反向
grade = models.student.objects.filter(name="张三").values("grade__score")
# 正向
student = models.student.objects.filter(course__name="数学").values("name")
# 反向
student = models.course.objects.filter(name="数学").values("student__name")
#连续跨表查询
# 正向
grade = models.grade.objects.filter(student_id__name="张三").values("score","course_id__name")
#反向
grade = models.student.objects.filter(name="张三").values("grade__score","grade__course_id__name")

5.2.4、聚合查询

#所有人平均分-----aggregate的返回值是一个字典类型
grade_agv = models.grade.objects.all().aggregate(score_avg=avg("score"))
# 某个人的平均分
student_agv = models.grade.objects.filter(student_id__name="张三").aggregate(score_avg=avg("score"))
#求多个聚合
score = models.grade.objects.aggregate(avg_s=avg("score"),max_s = max("score"),min_s = min("score"))

5.2.5、分组查询

annotate()为调用的queryset中每一个对象都生成一个独立的统计值(统计方法用聚合函数

#根据学生姓名分组,求分数平均值,和分数最大值
#正向
grade = models.grade.objects.values("student_id__name").annotate(avg_s = avg("score"),max_s=max("score"))
#反向
score = models.student.objects.annotate(avg_s=avg("grade__score"),max_s=max("grade__score"),min_s=min("grade__score"))

5.2.6、f查询和q查询

上面查询只是将字段值与某个常量做比较。f和q查询可以对两个字段的值做比较

# f可以比较两个不同字段的值
# 查询学生课程连表,课程id=学生id的数据
from django.db.models import f
sc = models.studentcourse.objects.filter(course_id=f('student_id'))
# f对象支持和常数之间的加减乘除和取模的操作
sc = models.studentcourse.objects.filter(course_id=f('student_id')+1).all()
sc = models.studentcourse.objects.filter(course_id=f('student_id')*2).all()
q 对象可以使用& 、|、~ 操作符组合起来。当一个操作符在两个q 对象上使用时,它产生一个新的q 对象。
from django.db.models import q
# or查询
students = models.student.objects.filter(q(name="张三")| q(name="李四"))
# 查询名字为张三或者,没选数学课程的学生
students = models.student.objects.filter(q(name="张三") | ~q(course__name="数学")).values("name")
# 复杂的查询
students = models.student.objects.filter((q(age__lt=20) & q(grade__score__gt=70)) | (q(age__gt=24) & q(grade__score__lt=60))).values("name")

5.3、改

# update更新
res = models.student.objects.filter(name="张三").update(name="章三")
# save更新
student = models.student.objects.filter(name="章三").first()
student.name = "张三"
student.save()

5.4、删

# delete删除
models.student.objects.filter(name="张三").delete()
# 对象delete删除
student = models.student.objects.get(id=2)
student.delete()

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com