零基础入手Django(八):模型基础3

今天,小叮当来继续为大家分享Django的干货~

主要内容有:表的级联删除、表关联对象的访问、表关联对象的补充、关系表的数据操作和多表查询。

首先,我们接着昨天所建的项目db_test,为其配置路由

(1)为db_test新建urls.py文件

(2)在主路由中为db_test分配子路由

(3)设置db_test的views.py定义视图函数

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

from django.shortcuts import render

# Create your views here.

from django.http import HttpResponse

#导入学院表、学生表、学生详细信息表、课程表

from .models import Department,Student,Stu_detail,Course

def test(request):

Department.objects.create(d_name='计算机')

Department.objects.create(d_name='音乐')

Department.objects.create(d_name='艺术')

Department.objects.create(d_name='金融')

Department.objects.create(d_name='英语')

Student.objects.create(s_name='小叮当',department_id=1)

Student.objects.create(s_name='少年叮当', department_id=2)

Student.objects.create(s_name='青年叮当', department_id=3)

Student.objects.create(s_name='任性叮当', department_id=4)

Student.objects.create(s_name='国外叮当', department_id=5)

return HttpResponse('小叮当在往学院表和学生表里建数据')

(4)在db_test的urls.py中配置对应的路由

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

from django.urls import path

from . import views

urlpatterns = [

path('test/',views.test),

]

(5)在浏览器中访问

(6)通过xshell进行查看

可以看到,学院表和学生表已成功创建。

一、表的级联删除

(1)在主表中删除数据,对应表中的数据也会被删除。

例如,将学院表中的计算机学院删除,对应学生表中属于计算机学院的小叮当则也会被删除。

重新定义db_test中views.py里的视图函数test

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

from django.shortcuts import render

# Create your views here.

from django.http import HttpResponse

#导入学院表、学生表、学生详细信息表、课程表

from .models import Department,Student,Stu_detail,Course

def test(request):

Department.objects.get(d_id=1).delete()

return HttpResponse('小叮当将学院表中id=1的学院删除了')

在浏览器中访问,使视图函数运行

通过xshell查看数据库

可见计算机学院从学院表中删除后,与之关联的学生表中的小叮当也被删除了。

(2)设置默认值为空的级联删除

当我们进行级联删除时,只想删除主表中的数据以及其他表对它的引用,而不删除其他表中的数据时,该怎么做呢?

例如,我想删除学院表中id=2的音乐学院和学生表中对音乐学院的引用,而不删除学生表中的少年叮当

首先,我们可以在xshell中进入mysql

执行 show create table db_test_student\G 查看创建db_test_student表的mysql语句 "\G"表示结果按列输出

可以看到,department_id不允许为空

我们在models.py中更改表结构,将学生信息表中的on_delete其设置为默认值为空的级联删除

具体代码如下:

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

#2.创建学生信息表

class Student(models.Model):

s_id = models.AutoField(primary_key=True)

s_name = models.CharField(max_length=30)

#实现一对多关系ForeignKey 其中on_delete使用默认值为空的级联删除

department = models.ForeignKey('Department',on_delete=models.SET_NULL,null=True)

(当然,如果不想执行级联删除,可以on_delete=models.PROTECT 将其保护起来)

更改表结构后,执行映射等操作。

在Tools中找到Run manage.py Task...

执行makemigrations

执行migrate

之后在xhell的mysql中再次查看表结构,发现department_id字段已默认为空

重新定义db_test中views.py里的视图函数test

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

from django.shortcuts import render

# Create your views here.

from django.http import HttpResponse

#导入学院表、学生表、学生详细信息表、课程表

from .models import Department,Student,Stu_detail,Course

def test(request):

Department.objects.get(d_id=2).delete()

return HttpResponse('小叮当将学院表中id=2的学院删除了')

在浏览器中访问

通过xshell查看数据库

二、表关联对象的访问

1.一对多关联 学院表和学生表

(1)在models.py中重新定义模型类,为学院表和学生表加上自定义输出def __str__(self)

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

#1.创建学院信息表

class Department(models.Model):

d_id = models.AutoField(primary_key=True)

d_name = models.CharField(max_length=30)

def __str__(self):

return 'Department' % (self.d_id,self.d_name)

#2.创建学生信息表

class Student(models.Model):

s_id = models.AutoField(primary_key=True)

s_name = models.CharField(max_length=30)

#实现一对多关系ForeignKey 其中on_delete为必填字段使用级联删除CASCADE

department = models.ForeignKey('Department',on_delete=models.CASCADE,null=True)

def __str__(self):

return 'Students'%(self.s_id,self.s_name,self.department_id)

(2)重新定义视图函数

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

def test(request):

d1 = Department.objects.get(d_id=3) #一个学院类的实例对象

s1 = Student.objects.get(s_id=3)#一个学生类的实例对象

print(s1.department,type(s1.department))#学生所属学院

print(s1.department.d_name)#学生所属学院的名称

stu=d1.student_set.all() #学院里所属的学生(反向查询)

print(stu)

return HttpResponse('小叮当在进行表关联对象的访问')

(3)在浏览器中访问

(4)在后台查看输出

小结:在学生表查询到的学生信息相当于学生类的实例对象,可以直接像访问成员函数那样访问学院类中的属性,以此来实现表关联对象的访问。

值得注意,学生表关联了学院表,想查询学院有哪些学生时就属于反向查询了。

反向查询

(1)直接反向查询

直接反向查询,是通过查询关键字加”_set"来实现的,例如“student_set",如果表关系是一对一,则不加_set也可。

(2)重命名查询 related_name

通过在模型类中添加related_name的方法,也可进行反向查询

具体代码如下

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

#2.创建学生信息表

class Student(models.Model):

s_id = models.AutoField(primary_key=True)

s_name = models.CharField(max_length=30)

#实现一对多关系ForeignKey 其中on_delete为必填字段使用级联删除CASCADE

department = models.ForeignKey('Department',on_delete=models.CASCADE,related_name='students')

def __str__(self):

return 'Students'%(self.s_id,self.s_name,self.department_id)

此时进行反向查询时,使用students即可。因为系统中已经没有了student_set属性,若还按student_set查询则会报错

在视图函数中改为用students查询,即可成功查询

2.一对一关联 学生表和学生详细表

(1)查看学生信息详细表 和学生表 

(2)models.py中在学生详细模型类中自定义输出 def__str__(self)

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

#4.学生详细信息表

class Stu_detail(models.Model):

# 实现一对一关系OneToOneField 其中on_delete为必填字段使用级联删除CASCADE

student = models.OneToOneField('Student',on_delete=models.CASCADE)

age = models.IntegerField()

gender = models.BooleanField(default=1)

city = models.CharField(max_length=30,null=True)

def __str__(self):

return 'Stu_detail'%(self.student_id,self.age,self.gender,self.city)

(3)views.py中根据表字段创建数据表

由于学生详细信息表关联的是学生表,所以在创建学生详细表时,id要从学生表里现在有的”2、3、4、5“中创建。

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

from django.shortcuts import render

# Create your views here.

from django.http import HttpResponse

#导入学院表、学生表、学生详细信息表、课程表

from .models import Department,Student,Stu_detail,Course

def test(request):

Stu_detail.objects.create(age=18,gender=0,city='洛阳',student_id=3)

return HttpResponse('小叮当在创建学生详细信息表')

在浏览器中访问触发视图函数

在数据库中查看

(4)重新定义视图函数

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

from django.shortcuts import render

# Create your views here.

from django.http import HttpResponse

#导入学院表、学生表、学生详细信息表、课程表

from .models import Department,Student,Stu_detail,Course

def test(request):

std = Stu_detail.objects.get(id=1) #一个学生的详细信息

print(std.student.s_name) #正向查询

print(s1.stu_detail) #反向查,直接类名小写

return HttpResponse('小叮当在实现一对一表关系的对象访问')

(5)在浏览器中访问

(6)在后台查看

3.多对多关联 学生表和课程表

(1)查询课程表字段

根据字段在views.py中为课程表添加数据

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

from django.shortcuts import render

# Create your views here.

from django.http import HttpResponse

#导入学院表、学生表、学生详细信息表、课程表

from .models import Department,Student,Stu_detail,Course

def test(request):

Course.objects.create(c_name='Python')

Course.objects.create(c_name='自然语言处理')

Course.objects.create(c_name='养猪')

Course.objects.create(c_name='推塔与补兵')

Course.objects.create(c_name='如何对线')

Course.objects.create(c_name='摄影')

return HttpResponse('小叮当在创建课程表')

在浏览器中访问

在数据库中查看

在models.py中为课程表自定义输出 def __str__(self)

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

#3.课程信息表

class Course(models.Model):

c_id = models.AutoField(primary_key=True)

c_name = models.CharField(max_length=30)

student = models.ManyToManyField('Student')

def __str__(self):

return 'Course'%(self.c_id,self.c_name)

由于访问方法和之前的一样,这里不再演示,在views.py中定义代码如下

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

s4 = Student.objects.get(s_id=4) #一个学生的实例

c1 = Course.objects.get(c_id=1) #一个课程的实例

print(c1.student.all()) #正向查询

#print(s4.course_set.all()) #反向查询 默认的是course_set

print(s4.courses.all()) #related_name 指定名字为courses

三、表关联对象的补充

在表关联中的正向查询是指,一个表的模型类可以在另个一表的模型类中找到。

例如,在课程表的模型类中可以直接访问到学生表模型类

那么,查询一门课程所选的学生就是正向查询。反之查询学生选了哪些课就是反向查询。

四、关系表的数据操作

1.数据的添加

(1)一对多关系 add()添加已经存在的数据   create()添加新的数据

在views.py中重新定义视图函数

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

def test(request):

d3 = Department.objects.get(d_id=3)

s3 = Student.objects.get(s_id=3)

std = Stu_detail.objects.get(id=1)

c1 = Course.objects.get(c_id=1)

sn_xdd = Student.objects.get(s_id=2)

#一对多关系 数据的添加 add() 添加的数据首先已存在

d3.students.add(sn_xdd)

gw_xdd = Student.objects.get(s_id=5)

#如果原有学生已有所属学院 add则可起到修改的作用

#将s_id=5的学生所属院改为d_id=3的学院

d3.students.add(gw_xdd)

#新建数据 create()

d3.students.create(s_name='测试小叮当1')

d3.students.create(s_name='测试小叮当2')

return HttpResponse('小叮当在进行一对多关系表的数据添加')

在浏览器中访问触发视图函数

在数据库中查看

(2)多对多关系add()添加已经存在的数据   create()添加新的数据

在views.py中重新定义视图函数

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

def test(request):

d3 = Department.objects.get(d_id=3)

s3 = Student.objects.get(s_id=3)

std = Stu_detail.objects.get(id=1)

c1 = Course.objects.get(c_id=1)

sn_xdd = Student.objects.get(s_id=2)

# #一对多关系 数据的添加 add() 添加的数据首先已存在

# d3.students.add(sn_xdd)

gw_xdd = Student.objects.get(s_id=5)

'''多对多'''

c2 = Course.objects.get(c_id=2)

#添加 3号学生选了1号和2号课程

s3.courses.add(c1,c2)

#新建 学院为3号学生开设了英雄联盟课程

s3.courses.create(c_name='英雄联盟')

return HttpResponse('小叮当在进行多对多关系表的数据添加')

在浏览器中访问 触发视图函数

在数据库中查找课程表、课程-学生中间信息表

2.数据删除 remove() 和clear()

(1)remove()

一对多关系的表使用remove删除时,必须保证外键列允许为空

例如,学院表和学生的对应关系

多对多关系,使用remove删除,删除掉的是中间信息表

在视图函数中定义

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

def test(request):

d3 = Department.objects.get(d_id=3)

s3 = Student.objects.get(s_id=3)

std = Stu_detail.objects.get(id=1)

c1 = Course.objects.get(c_id=1)

sn_xdd = Student.objects.get(s_id=2)

gw_xdd = Student.objects.get(s_id=5)

c2 = Course.objects.get(c_id=2)

d3.students.remove(sn_xdd)

s3.courses.remove(c1,c2)

return HttpResponse('小叮当在使用remove进行关系表的数据删除')

在浏览器中访问

在数据库中查询

(2)clear()进行清空

使用print查看3号学生选了哪些课程

定义视图函数

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

def test(request):

s3 = Student.objects.get(s_id=3)

print(s3.courses.all())

return HttpResponse('小叮当在查看3号学生的选课')

浏览器中访问

后台中查看

定义视图函数使用clear

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

def test(request):

s3 = Student.objects.get(s_id=3)

print(s3.courses.all())

s3.courses.clear()

return HttpResponse('小叮当使用clear清除了3号学生的选课')

浏览器中访问

后台查询

数据库中查询中间课程-学生信息表

可见,clear()会将符合条件的数据全部清空0

五、多表查询

多表查询又被称为是跨关联关系的查询。

Django 提供一种强大而又直观的方式来“处理”查询中的关联关系,它在后台自动帮你处理JOIN。 若要跨越关联关系,只需使用关联的模型字段的名称,并使用双下划线分隔,直至你想要的字段。

1.重建学生选课数据

在views.py中重新定义视图函数

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

def test(request):

d3 = Department.objects.get(d_id=3)

s3 = Student.objects.get(s_id=3)

std = Stu_detail.objects.get(id=1)

c1 = Course.objects.get(c_id=1)

sn_xdd = Student.objects.get(s_id=2)

# #一对多关系 数据的添加 add() 添加的数据首先已存在

# d3.students.add(sn_xdd)

gw_xdd = Student.objects.get(s_id=5)

'''多对多'''

c2 = Course.objects.get(c_id=2)

#添加 3号学生选了1号和2号课程

s3.courses.add(c1,c2)

#新建 学院为3号学生开设了英雄联盟课程

s3.courses.create(c_name='英雄联盟')

return HttpResponse('小叮当在进行选课数据的重建')

在浏览器中访问 触发视图函数

在数据库中查看

2.进行多表查询

在views.py中重新定义视图函数

#!/usr/bin/env python

# -*- coding:utf-8 -*-

__author__ = 'IT小叮当'

__time__ = '2019-02-19 15:21'

def test(request):

#1.查询学院名字为'艺术’的学生信息

ds = Student.objects.filter(department__d_name='艺术')

print('查询1',ds)

#2.查询学生名字中包含‘测试’的学生的学院信息

sd=Department.objects.filter(students__s_name__contains='测试')

print('查询2',sd)

#3.查询学号为3的学生的所有课程

sc = Course.objects.filter(student__s_id=3)

print('查询3',sc)

#4.查询报了课程1的所有学生的信息

cs = Student.objects.filter(courses__c_id=1)

print('查询4',cs)

#5.查询报了python课程的学生的所属学院信息

psd = Department.objects.filter(students__courses__c_name= 'python')

print('查询5',psd)

return HttpResponse('小叮当在进行多表查询')

在浏览器中查看

在后台查看

对照数据库进行检验

经检查查询结果正确,可见Django的多表查询结果是十分便捷的了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,978评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,954评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,623评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,324评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,390评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,741评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,892评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,655评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,104评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,569评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,254评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,834评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,725评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,950评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,260评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,446评论 2 348

推荐阅读更多精彩内容