我正在建立一个论坛,其中一个人发布消息,其他几个人回复它。
我有一个消息模型和响应模型如下:
class Messages (models.Model):
author = models.ForeignKey(User)
message = models.TextField()
def __unicode__(self):
return self.message
class Responses (models.Model):
message = models.ForeignKey(Messages)
responder = models.ForeignKey(User, related_name='responder')
rsp_to = models.ForeignKey(User, related_name='rsp_to')
rsp_from = models.ForeignKey(User, related_name='rsp_from')
response = models.TextField()
pub_date = models.DateTimeField('date_published')
def __unicode__(self):
return self.message
我想获得一个根据响应者组织的查询集,以便最新响应者的所有响应都是第一个,第二个最新响应者的响应是第二个,依此类推。
db表示例:
pk message responder rsp_to rsp_from response pub_date
------------------------------------------------------------
1 a User.2 a.author User.2 .... 1
2 a User.3 a.author User.3 .... 2
3 a User.3 User.3 a.author .... 3
4 a User.4 a.author User.4 .... 4
5 a User.4 User.4 a.author .... 5
6 a User.2 User.2 a.author .... 6
7 a User.3 a.author User.3 .... 7
8 a User.3 User.3 a.author .... 8
9 a User.4 a.author User.4 .... 9
重新排序的查询集:
pk message responder rsp_to rsp_from response pub_date
------------------------------------------------------------
9 a User.4 a.author User.4 .... 9
5 a User.4 User.4 a.author .... 5
4 a User.4 a.author User.4 .... 4
8 a User.3 User.3 a.author .... 8
7 a User.3 a.author User.3 .... 7
3 a User.3 User.3 a.author .... 3
2 a User.3 a.author User.3 .... 2
6 a User.2 User.2 a.author .... 6
1 a User.2 a.author User.2 .... 1
或者表示为:
r = [<all responses from latest responder>, <all responses from 2nd latest responder>,..., <all responses from earliest responder>]
如果我从:
开始r = Responses.objects.filter(message="a").order_by('-pub_date')
我先得到最新的回复。如何重新排序查询集,以便来自最新唯一响应者的所有响应在查询集中首先分组,来自第二个唯一响应者的所有响应都分组到第二个,依此类推?
答案 0 :(得分:0)
让我们首先考虑使用旧的sorted()
函数在Python中进行排序。它是comparison sort的一种类型,即它通过成对比较项目,一次一对,以及每一对决定哪一个应该首先进行排序。比较排序仅在比较器(作为排序参数给出的函数)定义total order:
因此,如果您可以定义一个比较器,它从您的表中获取两行并决定哪一行先行,并且该比较器定义了一个总顺序,那么您只需使用该比较器调用sorted
。
但是这样的比较器根本不存在你的问题。当两个不同的用户只考虑两行时,你永远不知道哪一个应该先出现。您将始终需要了解这些作者的最新帖子。结论:您无法使用sorted()
我不知道SQL是否可以处理这个问题。尝试并重写你的问题,省略所有Django和Python的东西,只有你拥有的表。如果您创建了这样的问题,请在此问题中添加一个链接。如果SQL可以处理它,那么您可以调用Responses.objects.sql()
。
下面的代码是如何使用存储桶对您想要的方式进行排序的示例。我使用了一个虚拟类响应,专注于原则。
from random import randint, shuffle
# == Data definition ==
class Response:
user = None #int
time = None #int
def __str__(self):
return '(%d:%2d)' % (self.user,self.time)
# == Create random data ==
responses = []
for i in range(20):
r = Response()
r.user = randint(1,4)
r.time = i
responses.append(r)
shuffle(responses)
# == Put in buckets ==
bucketdict = {}
for r in responses:
if r.user in bucketdict:
bucketdict[r.user].append(r)
else:
bucketdict[r.user] = [r]
# == create list from dict ==
bucketlist = bucketdict.items()
def printbucketlist():
for user,user_rsps in bucketlist:
print user,
for rsp in user_rsps:
print rsp,
print
print
printbucketlist()
# == Sort responses within each bucket ==
def rsp_comparator(r1,r2):
return r2.time - r1.time
for user,responses in bucketlist:
responses.sort(rsp_comparator)
printbucketlist()
# == Sort bucketlist ==
def bucket_cmp(b1,b2):
# assumes that the first response in the list has the highet time
return b2[1][0].time - b1[1][0].time
bucketlist = sorted(bucketlist,cmp=bucket_cmp)
printbucketlist()
# == Concatenate into one list ==
sortedresponses = []
for user, user_rsps in bucketlist:
for response in user_rsps:
sortedresponses.append(response)
for response in sortedresponses:
print response