c语言sscanf函数的用法是什么
339
2022-09-16
Django ManyToManyField 查询数据 按添加时间排序
在Django中,ManyToManyField是常用的Field,实现数据库中多对多模型。
例如,人与团体的关系(一个人可加入多个团体,一个团体有多个人):
class Person(models.Model): name = models.CharField(max_length=50)class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person, related_name='groups')
但是,当我们通过group.members(或person.groups)获取一个组织的所有成员(或获取这个人参加的所有组织)时,拿到的数据是按照group_id (或person_id)排列的,有时这样的行为不符合预期:
比如前端展示这个团体的人,希望是按照加入顺序来展示,而非按照人的id排序。
试想,当团队人数很多,你加了一个人后,他不是出现在最后,而是钻在一群人的中央,你很可能找不到他了!甚至怀疑自己有没有添加成功。这种类似的场合很常见
解决方案(无需改变数据库结构)
Django在实现ManyToManyField时,会默默引入一张“中间表”,它默认包括3列:id、model1_id、model2_id。以上面的Person和Group为例,这3列就是:id、person_id、group_id。这个id是自增索引,当然也意味着:建立的时间晚,id相对就大。我们可以通过id来实现“按添加时间排列”,而无需对数据库结构做任何改变!
为了实现它,我们获取数据的方式需要适当改变:
group1 = Group.objects.get(id=1)# 之前的方式,数据按 person_id 排列group1.members.all()# 改变后,数据按添加时间排列Group.members.through.objects.filter(group=group1).order_by('id').all()
原理是什么?
刚才提到,Django会默默引入一张“中间表”,这张“中间表”其实也是对应着一个隐藏的"Modal"的(生成顺序其实是Django先生成隐藏的Modal,再根据这个Modal生成那个数据库表)。Group.members.through这句话其实是引用了那个隐藏的"Modal"。它后面的.objects,就像对待普通Modal一样,对待它就可以了。
“隐藏的Modal”是什么?
在本文开头的例子,隐藏的"Modal"长这个样子:
class Person_Group(models.Model): group = models.ForeignKey(Group, on_delete=models.CASCADE) person = models.ForeignKey(Person, on_delete=models.CASCADE)
它生成的数据库表就是3列:id、person_id、group_id。
其实,这张表你也可以自己定义出来,不让Django自动生成,只是你需要多提供一个参数throuth给ManyToManyField:
class Person(models.Model): name = models.CharField(max_length=50)class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person, through='Membership')class Membership(models.Model): group = models.ForeignKey(Group, on_delete=models.CASCADE) person = models.ForeignKey(Person, on_delete=models.CASCADE) invite_reason = models.CharField(max_length=64)
这里我们给中间表起了名字Membership,名字随意起,through参数跟名字是对应的就行。
为什么through是写的字符串'Membership',而非直接写Membership?
因为Python解析器解析类的定义时,会把类的属性、方法都定义完,才会继续解析下一个类(在定义members时,Membership尚未被解析,此时如果引用它会报错,所以Django面对这种问题的解决方案就是——先用字符串代替,这是很常见的做法)
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~