day43-模型关系映射

2019-01-03  本文已影响0人  barriers

导入函数或者文件方法:先写一个函数名或者其他,然后按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()方法来创建、删除关系

上一篇下一篇

猜你喜欢

热点阅读