day43-模型关系映射

导入函数或者文件方法:先写一个函数名或者其他,然后按alt+enter
ctrl+d 快速复制当前行并粘贴到下一行
ctrl+y 删除当前行
模型层
ORM技术:对象关系映射 ---objects relationship mapping
对象关系映射:将模型中的语句映射为数据库中的语句,可以通过编写模型中的语句对数据库(多种)进行操作
objects:管理器,默认模型的属性
在orm技术中,pk代表表格的主键(primary key)

1添加学生对象(create)

创建 create()方法:模型名.objects.create(字段1=值,字段2=值)
save方法:模型对象.save()

1.1create方法

def add_stu(request):
    Student.objects.create(s_name='小明')
    return HttpResponse('创建学生成功')

1.2save方法

def add_stu(request):
    stu = Student()
    stu.s_name = '老王'
    stu.s_gender = 1
    stu.save()
    return HttpResponse('创建学生成功')

2删除学生

删除学生的步骤:
1.获取删除的对象,filter(条件)
2.实现删除方法 delete()
删除 delete()方法:模型名.objects.filter(条件).delete()

def del_stu(request):
    Student.objects.filter(id=13).delete()
    return HttpResponse('删除成功')

3更新(修改)学生

更新学生步骤:
1.获取更新的数据,filter(条件)
2.实现更新方法, update()
修改 update()方法:模型名.objects.filter(条件).update(字段1=值,字段2=值)
save()方法:模型对象.save
update()和save()的区别:是否更新使用auto_now约束条件的字段,(update不更新)

3.1update方法

def up_stu(request):
    Student.objects.filter(id=4).update(s_name='妲己')
    return HttpResponse('更新成功')

3.2save方法

def up_stu(request):
    stu = Student.objects.filter(id=2).first()
    stu.s_name = '妲己2'
    stu.save()
    return HttpResponse('更新成功')

4查询学生

4.1查询所有学生

查询所有的学生信息,all(),返回一组对象的列表

def sel_stu(request):
    stus = Student.objects.all()
    for stu in stus:
        print(stu.s_name)

4.2查询特定的单个学生

4.2.1filter方法

返回的是queryset对象

stu5 = Student.objects.filter(id=6)
print(stu)  # <QuerySet [<Student: Student object (6)>]>

first():取出结果中的第一个对象

stu = Student.objects.filter(id=6).first()
print(stu)  # Student object (6)

4.2.2get()方法

get()只能用来取唯一的一个对象
get(条件)条件必须成立才能使用

stu = Student.objects.get(id=6)
print(stu)  # Student object (6)(返回id为6的学生对象)

4.3查询特定的多个学生

stus = Student.objects.filter(s_gender=1)
print(stus) #查询所有的男性

4.4exclude(条件)方法

exclude(条件):过滤出不满足条件的信息

stus = Student.objects.exclude(s_gender=0)
print(stus)#查询所有性别为女的之外的性别的人(即查询全部男性)

4.5order_by()排序方法

order_by('id'),升序
order_by('-id'),降序

stus = Student.objects.order_by('id')
print(stus)

4.6values()方法

values()取出对象中的某个字段-返回的是一个列表,列表中为字典

stus = Student.objects.all().values('s_name', 's_age') #取所有人的姓名和年龄
stus1 = Student.objects.all().values() #取所有人的所有信息
print(stus, stus1)

4.7exists()方法、len()方法及count()方法

exists()方法 - 判断查询信息存在否,返回布尔值

# 判断小张这个人存在不
a = Student.objects.filter(s_name='小张').exists()
print(a)  # False

stus = Student.objects.filter(s_gender=1)
# len查看查询结果的长度
print(len(stus))  # 2

# count统计查询结果元素的个数
b = Student.objects.filter(s_gender=1).count()
print(b)  # 2

4.8模糊查询(contains、startswith及endswith)

4.8.1contains方法

contains:包含,模糊查询;语法,字段__contains=

stus = Student.objects.filter(s_name__contains='小明')
print(stus)

4.8.2startswith方法

startswith:以什么开头

stus = Student.objects.filter(s_name__startswith='小')
print(stus)

4.8.3endswith方法

endswith:以什么结束

stus = Student.objects.filter(s_name__endswith='明')
print(stus)

4.9in方法

in:查询在某个范围之内

stus = Student.objects.filter(id__in=[1, 2, 3, 4, 5])
print(stus)

stus = Student.objects.filter(pk__in=[1, 2, 3, 4, 5])
print(stus)

pk代表主键,而id是这个学生表的主键,所以结果将一样

4.10大于及小于符号

gte:大于等于;gt:大于;lte:小于等于;lt:小于
在比较符号后面必须是一个值

stus = Student.objects.filter(s_age__gte=21, s_age__lte=23)
stus=Student.objects.filter(s_age__gte=21).filter(s_age__lte=23)

上面两条语句的结果相同,都为查询年龄大于等于21且小于等于23的人

4.11与或非

用与或非语句的时候,需要先导入Q方法

4.11.1与

stus = Student.objects.filter(s_age__gte=21, s_age__lte=23)
stus = Student.objects.filter(Q(s_age__gte=21), Q(s_age__lte=23))
stus = Student.objects.filter(Q(s_age__gte=21) and Q(s_age__lte=23))
stus = Student.objects.filter(Q(s_age__gte=21) & Q(s_age__lte=23))

4.11.2或

stus = Student.objects.filter(Q(s_age__gte=21) or Q(s_age__lte=23))
stus = Student.objects.filter(Q(s_age__gte=21) | Q(s_age__lte=23))

4.11.3非

stus = Student.objects.filter(~Q(s_age__gte=21))

4.11.4对象属性比较

查询物理成绩大于数学成绩的学生

stus = Student.objects.all()
for stu in stus:
    if (stu.wuli > stu.math):
        print(stu.s_name)

上面方法也能达到要求,但不推荐;推荐使用下面方法
F('math'):取math对应的值

stus = Student.objects.filter(wuli__gt=F('math'))

4.12聚合函数Avg,Max,Sum,Count

def sel_stu(request):
    age_avg = Student.objects.all().aggregate(Avg('s_age'))
    print(age_avg)
    age_sum = Student.objects.all().aggregate(Sum('s_age'))
    print(age_sum)
    return HttpResponse('查询所有学生信息')

5多对多关系中自定义中间表

一般情况,普通的多对多已经够用,无需自己创建第三张关系表。但是某些情况可能更复杂一点,比如如果你想保存某个人加入某个分组的时间呢?想保存进组的原因呢?
Django提供了一个through参数,用于指定中间模型,你可以将类似进组时间,邀请原因等其他字段放在这个中间模型内。例子如下:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=128)
    def __str__(self): 
        return self.name

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')
    def __str__(self): 
        return self.name

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()        # 进组时间
    invite_reason = models.CharField(max_length=64)  # 邀请原因

使用中间表

ringo = Person.objects.create(name="Ringo Starr")
paul = Person.objects.create(name="Paul McCartney")

beatles = Group.objects.create(name="The Beatles")

m1 = Membership(person=ringo, group=beatles,
      date_joined=date(1962, 8, 16),
      invite_reason="Needed a new drummer.")

m1.save()
# 查看分组下所有成员
beatles.members.all()
# 查看成员所属分组
ringo.group_set.all()

与普通的多对多不一样,使用自定义中间表的多对多不能使用add(), create(),remove(),和set()方法来创建、删除关系

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

推荐阅读更多精彩内容