1.mysql
的相关配置 1.1 驱动安装
1.2 修改 settings.py
文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 DATABASES = { 'default' : { 'ENGINE' : 'django.db.backends.mysql' , 'NAME' : 'django7' , 'USER' : 'root' , 'PASSWORD' : 'pico123456' , 'HOST' : '127.0.0.1' , 'PORT' : '3306' , } }
1.3 在 mysql
中创建相应的数据库 1 create database django7;
1.4 测试是否连接成功
1 python manage.py makemigrations
1 python manage.py migrate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying auth.0012_alter_user_first_name_max_length... OK Applying sessions.0001_initial... OK
2. 多表之间的三种关系 2.1 一对一关系(1:1)
一个用户只有一个身份证号,一个身份证号只对应一个用户
user表
userid
name
idcard
001
张三
101
…
…
…
身份证表
idcard
address
date
101
北京
2025-01-01
…
…
…
2.2 一对多(1:N)
一个班有多一个学生
一个学生只属于一个班
注意外键只能写在数据多的一边
班级表
classid
cname
adress
111
一班
1 楼 1 教室
112
二班
2 楼 2 教室
…
…
…
学生表
stuid
sname
classid (外键)
1
张三
111
2
李四
111
3
王五
112
4
赵六
112
…
…
…
2.3 多对多 (N:M)
1 个用户可以收藏多个电影
1 个电影可以被多个用户收藏
1:N :M:1
用户表
userid
uname
age
101
张三
33
102
李四
44
103
王五
55
104
赵六
66
…
…
…
收藏表
(中间表)
collectid
userid
movieid
1
101
1001
2
101
1002
3
102
1003
4
102
1004
5
103
1001
…
…
…
电影表
movieid
mname
date
1001
电影 1
2023
1002
电影 2
2025
1003
电影 3
2024
1004
电影 4
2022
…
…
…
3. 一对多关系 models.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from django.db import modelsclass Classes (models.Model): name = models.CharField(max_length=100 ) def __str__ (self ): return self .name class Student (models.Model): name = models.CharField(max_length=100 ) age = models.IntegerField() classes = models.ForeignKey(Classes, on_delete=models.SET_DEFAULT, default=11 )
Django 模型关系中的 on_delete 参数有以下 7 种常用模式,以下是它们的典型使用场景说明:
1️⃣CASCADE(级联删除)
1 on_delete=models.CASCADE
当主表记录被删除时,自动删除所有关联的从表记录(适用于强关联关系,如「订单 - 订单明细」)
2️⃣PROTECT(保护删除)
1 on_delete=models.PROTECT
阻止删除主表记录(会抛出 ProtectedError),直到所有关联的从表记录被手动删除(适用于关键数据保护)
3️⃣SET_NULL(设空值)
1 on_delete=models.SET_NULL
当主表记录被删除时: 必须设置参数 **null=True
**
1 classes = models.ForeignKey(Classes, models.SET_NULL,null=True )
4️⃣SET_DEFAULT(设默认值)
1 classes = models.ForeignKey(Classes, on_delete=models.SET_DEFAULT, default=2 )
注意需要确保默认值在数据库中存在
5️⃣SET ()(自定义处理)
1 on_delete=models.SET(get_default_class)
可指定函数返回处理值:
1 2 def get_default_class (): return Classes.objects.get_or_create(name='未分配' )[0 ]
6️⃣DO_NOTHING(不干预)
1 on_delete=models.DO_NOTHING
需要手动处理数据库级联关系(通常配合数据库自身的外键约束使用)
7️⃣RESTRICT(限制删除)
1 on_delete=models.RESTRICT
与 PROTECT 类似但更智能:仅当存在直接关联的从表记录时阻止删除,允许通过中间表的间接关联被删除
1️⃣用户评论 → 使用 CASCADE(用户注销后删除所有评论)
2️⃣商品分类 → 使用 PROTECT(防止误删有商品的分类)
3️⃣可选关联项 → 使用 SET_NULL(如文章备用分类)
4️⃣系统默认项 → 使用 SET_DEFAULT(如默认用户组)
1 python manage.py makemigrations
1 python manage.py migrate
1 2 3 4 5 6 # 表名=应用名_类名小写 create table One2Many_classes ( id bigint auto_increment primary key, name varchar(100) not null );
这里需要注意的是,生成的外键是 **classes_id
, 而不是 classes
**
1 2 3 4 5 6 7 8 9 10 11 create table One2Many_student ( id bigint auto_increment primary key, name varchar(100) not null, age int not null, classes_id bigint not null, constraint One2Many_student_classes_id_2306c407_fk_One2Many_classes_id # 这里需要注意的是,生成的外键是 classes_id foreign key (classes_id) references One2Many_classes (id) );
3.1 增 按照 2 的表结构,新增
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 def add_classes (request ): classes = ['一年级' , '二年级' , '三年级' , '四年级' , '五年级' , '六年级' , '初一' , '初二' , '初三' , '高一' , '高二' ,'高三' ] for c in classes: c = Classes.objects.create(name=c) return HttpResponse('添加班级成功' ) def add_students (request ): class_id_list = Classes.objects.values_list('id' ) print (class_id_list) class_id_choice_list = [id [0 ] for id in class_id_list] print (class_id_choice_list) for i in range (1 , 101 ): Student.objects.create(name='学生' + str (i), age='10' , classes_id=choice(class_id_choice_list)) return HttpResponse('添加学生成功' ) def add_students2 (request ): class_list = Classes.objects.all () print (class_list[0 ]) print (type [class_list[0 ]]) for i in range (101 , 201 ): selected_class = choice(class_list) Student.objects.create(name='学生' + str (i), age='10' , classes=selected_class) return HttpResponse('添加学生成功' )
3.2 删
这里删除时,注意 **on_delete
** 中的参数
修改 on_delete
参数时,需要生成迁移文件,执行迁移。
views.py
1 2 3 4 5 6 7 8 9 10 def delete_classes (request ): Classes.objects.filter (name='四年级' ).delete() return HttpResponse('删除年级成功' ) def delete_students (request ): Student.objects.filter (id =4 ).delete() return HttpResponse('删除学生成功' )
3.3 改
views.py
1 2 3 4 5 6 7 8 9 10 def update_classes (request ): Classes.objects.filter (id =7 ).update(name='七年级' ) return HttpResponse('修改班级成功' ) def update_students (request ): Student.objects.filter (id =4 ).update(age='88' ) return HttpResponse('修改学生成功' )
3.4 查 3.4.1 正向
views.py
1 2 3 4 5 6 7 8 9 10 def query_classes (request ): s1 = Student.objects.get(id =4 ) c1 = s1.classes print (c1.name) return HttpResponse('查询班级成功' )
3.4.2 反向 1
views.py
1 2 3 4 5 6 7 8 9 10 11 12 13 def query_students (request ): c1 = Classes.objects.get(id =8 ) print (c1.name) ss1 = c1.student_set.all () print (c1.name, '的学生有:' ) for s in ss1: print (s.name) return HttpResponse('查询学生成功' )
3.4.3 反向 2
使用 **related_name
**(管理器对象), 通过班级查询到学生
models.py
1 2 3 4 5 6 7 8 class Student (models.Model): name = models.CharField(max_length=100 ) age = models.IntegerField() classes = models.ForeignKey(Classes, on_delete=models.CASCADE, related_name='students' )
views.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def query_students2 (request ): c1 = Classes.objects.get(id =8 ) print (c1.name) ss1 = c1.students.all () print (c1.name, '的学生有:' ) for s in ss1: print (s.name) return HttpResponse('查询学生成功' )
3.3.4 反向 3
1 2 3 4 5 6 7 8 9 10 11 def query_students3 (request ): students = Student.objects.filter (classes__id='2' ) print (students) return HttpResponse('查询学生3成功' )
4. 多对多关系
针对多对多的关系,django
会自动创建第三张表,也可以通过 through
参数指定第三张表。
models.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Users (models.Model): name = models.CharField(max_length=100 ) age = models.IntegerField() def __str__ (self ): return self .name class Movies (models.Model): name = models.CharField(max_length=100 ) year = models.IntegerField() users = models.ManyToManyField(Users) def __str__ (self ): return self .name
1 2 python manage.py makemigrations python manage.py migrate
4.1 增 4.1.1 单表直接添加 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 def add_movies (request ): for i in range (1 , 20 ): Movies.objects.create(name='电影' + str (i), year=i + 2000 ) return HttpResponse('添加电影成功' ) def add_users (request ): for i in range (1 , 20 ): Users.objects.create(name='用户' + str (i), age=i + 18 ) return HttpResponse('添加用户成功' ) def add_movie_user2 (request ): user6 = Users.objects.get(id =6 ) user7 = Users.objects.get(id =7 ) user8 = Users.objects.get(id =8 ) movie4 = Movies.objects.get(id =4 ) user6.movies_set.add(movie4) user7.movies_set.add(movie4) user8.movies_set.add(movie4) return HttpResponse('用户收藏电影成功' )
4.1.2 使用 add
添加关联关系表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 def add_movie_user (request ): user1 = Users.objects.get(id =1 ) user2 = Users.objects.get(id =2 ) user3 = Users.objects.get(id =3 ) user4 = Users.objects.get(id =4 ) user5 = Users.objects.get(id =5 ) movie1 = Movies.objects.get(id =1 ) movie2 = Movies.objects.get(id =2 ) movie3 = Movies.objects.get(id =3 ) movie1.users.add(user1, user2) movie2.users.add(user1, user3) movie3.users.add(user1, user4) movie1.users.add(user5) movie2.users.add(user5) movie3.users.add(user5)
4.1.3 使用_set
方法添加关联关系表 1 2 3 4 5 6 7 8 9 10 11 12 13 def add_movie_user2 (request ): user6 = Users.objects.get(id =6 ) user7 = Users.objects.get(id =7 ) user8 = Users.objects.get(id =8 ) movie4 = Movies.objects.get(id =4 ) user6.movies_set.add(movie4) user7.movies_set.add(movie4) user8.movies_set.add(movie4) return HttpResponse('用户收藏电影成功' )
4.2 删 4.2.1 单表删除
和一对多类似,删除每一张单表
中的数据,会级联删除级联表
中的数据。
1 2 3 4 5 6 7 8 9 10 11 12 def delete_movies (request ): movie19 = Movies.objects.get(id =19 ) movie19.delete() return HttpResponse('删除电影成功' ) def delete_users (request ): user19 = Users.objects.get(id =19 ) user19.delete() return HttpResponse('删除用户成功' )
4.2.2 关联表删除
只删除关联关系表中的数据,使用 remove, 如果使用 delete, 则会删除用户中用户,然后级联删除关联中的表
1 2 3 4 5 6 7 8 def delete_related (request ): movie7 = Movies.objects.get(id =8 ) user7 = Users.objects.get(id =8 ) movie7.users.remove(user7) return HttpResponse('删除相关数据成功' )
4.3 改
4.4 查
1 2 3 4 5 6 7 8 9 10 11 12 def query_movies_users (request ): movie8 = Movies.objects.get(id =8 ) users_all = movie8.users.all () print (users_all) user8 = Users.objects.get(id =8 ) user8_movies = user8.movies_set.all () print (user8_movies) return HttpResponse('查询电影成功' )
5. 一对一关系
一对一关系不是数据库的一个连表操作,是 Django
独有的一个连表操作,一对一关系相当于一个特殊的一对多关系,只是相对于一对多添加了 **unique=True
**
models.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from django.db import modelsclass IdCard (models.Model): IdCard_number = models.IntegerField(unique=True ) address = models.CharField(max_length=100 ) class Person (models.Model): name = models.CharField(max_length=100 ) age = models.IntegerField(default=18 ) id_card = models.OneToOneField(IdCard, on_delete=models.CASCADE)
5.1 增、删、改
5.2 查 views.py
需要注意的是,无论是正向还是反向获取的都是一个对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def get_id_card (request ): p1 = Person.objects.get(pk=2 ) print (p1.id_card.IdCard_number) print (type (p1.id_card)) print (p1.id_card.address) return HttpResponse('查询成功' ) def get_person (request ): id_card3 = IdCard.objects.get(pk=3 ) print (id_card3.person) print (type (id_card3.person)) print (id_card3.person.name) return HttpResponse('查询成功' )
6. 相关参考 B 站视频