您的位置:首页 > 编程语言 > Python开发

python学习笔记-Day022 - django ORM操作

2016-04-20 16:46 721 查看
一对多:models.ForeignKey()
首先定义表结构:
class UserType(models.Model):
caption = models.CharField(max_length=32)
def __unicode__(self):
return self.caption

class UserInfo(models.Model):
username = models.CharField(max_length=32)
user_type = models.ForeignKey("UserType")
age = models.IntegerField()
def __unicode__(self):
return "%s%d" % (self.username,self.age)


在创建表的时候,一般情况下 ,默认会生成一列 id 列,用来做表的主键.ForeignKey 字段默认会关联表的id列.

增加数据
向 UserType插入数据
dic1 ={"caption":"AAA"}
models.UserType.objects.create(**dic1)
dic2 ={"caption":"BBB"}
models.UserType.objects.create(**dic2)
dic3 ={"caption":"CCC"}
models.UserType.objects.create(**dic3)
此时,我们向 UserType 表插入了三条数据, 因不涉及其他表,正常操作即可

向 UserInfo 插入数据:
第一种方式:
dic = {"username":"user01","age":12,"user_type":models.UserType.objects.get(id=2)}
models.UserInfo.objects.create(**dic)
第二种方式:
dic = {"username":"N","age":12,"user_type_id":1}
models.UserInfo.objects.create(**dic)
两种方式都可以,两种方式的区别是 UserInfo 表中的user_type 列 在django中实际上一个对象,这个对象就是UserType表, 在数据表中 UserInfo表的 实际字段是user_type_id , 因为这个区别, 就有了这两种数据插入的方式.

查询数据
正向查询:
这里的正常查是指从ForeignKey字段所在的表,向被关联的表查询, 以上面的数据表为例:
UserInfo表中的user_type为 ForeignKey 字段, 关联了 UserType表
查询数据的方式 是从 UserInfo 表查询 UserType表的数据
如果我们查询UserInfo 表中 所有用户类型为 AAA 的用户 , 那么语句为:
models.UserInfo.objects.filter(user_type__caption="AAA")


注意 : 这里的双下划线
UserInfo 表中的 user_type 字段 为一个对象, 每行对应 UserType表中的一条数据, 此时 ,我们使用 字段名 + 双下划线 即可 在UserInfo 表中查询 UserType 表的数据.

在我们查询数据的时候,如果需要跨表查询 ,那么我们只需使用关联的模型字段的名称,并使用双下划线分隔,直至你想要的字段

反向查询:
UserType 表中的一条数据 对应 UserInfo表中的多条数据, 如果我们希望通过 UserType 表 查询 UserInfo 表中的数据的话,查询语句为:
line  = models.UserType.objects.get(id=2)
line.userinfo_set.filter(username="N")
# 这一行是通过UserType 去UserInfo里查数据
models.UserInfo.objects.filter(user_type=line).filter(username="N")   #  等价于 上一行
例:
获取 用户 A 所属的用户类型,有多少人
models.UserType.objects.get(userinfo__username="A").userinfo_set.all().count()


注意:
userinfo_set 的来历:
_set 是 Django 也提供反向获取关联对象的 API ,
django在创建数据库的时候.自动给 UserType 表创建了一个 userinfo (和关联UserType的 UserInfo 表同名 , 但这里是小写) , 这里的 userinfo_set 对应的就是 UserInfo 表, 可以通过userinfo_set 在UserInfo表中进行数据查询.

一对多 总结
创建数据:
两种方式:
1. 直接使用 models中 设置的字段名
2. 使用models 中设置的字段名 + _id

正向查询

filter(对象__跨表字段名) #使用filter时

对象.跨表字段名 # 直接查询时

反向查询

filter() 自动创建的同名(小写)的对象__跨表的字段名

自动创建的同名(小写)的对象_set.filter()

多对多 :ManyToManyField
多对多的工作方式和一对多类似.
在使用多对多的时候, 会为关联的两张表 创建一张中间表, 用中间表来关联两张表.

创建表结构
class Host(models.Model):
hostname = models.CharField(max_length=32)
port = models.IntegerField()

class HostAdmin(models.Model):
username = models.CharField(max_length=32)
email = models.CharField(max_length=32)
host = models.ManyToManyField(Host)


增加数据:
models.Host.objects.create(hostname="Host1",port=1024)
models.Host.objects.create(hostname="Host2",port=1024)
models.Host.objects.create(hostname="Host3",port=1024)


models.HostAdmin
.objects.create(username="user01",email="a@a.com")
models.HostAdmin.objects.create(username="user02",email="b@a.com")
models.HostAdmin.objects.create(username="user03",email="c@a.com")


在向两张表中插入数据的时候, 并不需要设置表数据之间的关联.

关联两张表的数据的时候,有两种方式,

正向添加
admin_obj = models.HostAdmin.objects.get(username="someone")  # 获取用户对象
host_list = models.Host.objects.filter(id__lt=3)              # 获取指定主机
admin_obj.host.add(*host_list)                                # 将获取到的主机添加到 中间表


反向添加
host_obj = models.Host.objects.get(id=3)                            #获取主机对象
admin_list = models.HostAdmin.objects.filter(id__gt=1)    # 获取指定条件的管理员
host_obj.hostadmin_set.add(*admin_list)                            # 将数据添加到中间表


自定义中间表 (推荐使用)

有的时候,我们希望可以使用自定义的关联两张表的中间表,除了系统自动生成的字段,我们还可以添加其他字段.

创建表
class Host1(models.Model):
hostname = models.CharField(max_length=32)
port = models.IntegerField()

class HostAdmin1(models.Model):
username = models.CharField(max_length=32)
email = models.CharField(max_length=32)
host = models.ManyToManyField(Host1, through='HostRelation')

class HostRelation(models.Model):
c1 = models.ForeignKey(Host1)
c2 = models.ForeignKey(HostAdmin1)


通过使用 through= " " 可以设置使用指定的中间表 .

多对多的查询方法也分正向查和反向查, 用法和一对多 一样. 学会了一对多的使用,也就学会多对多的使用.需要注意的是, 未使用自定义中间表的时候, 需要使用关联的两张表去找到中间表,再进行查询.

使用自定义中间表后, 因为中间表 是我们指定的. 我们可以直接操作中间表, 而未使用自定义中间表的时候 ,我们需要使用关联表去查询中间表的数据, 相比较来说, 使用自定义表的方法更直观,更接近数据库中表关系. 在实际使用过程中, 还是推荐使用自定义中间表的方式.

本文出自 “Will的笔记” 博客,请务必保留此出处http://timesnotes.blog.51cto.com/1079212/1765868
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: