2

我正在建立一个论坛,一个人发布一条消息,其他几个人回复它。

我有一个消息模型和一个响应模型如下:

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

我想获得一个根据响应者组织的查询集,以便来自最新响应者的所有响应都是第一个,第二个最新响应者的响应是第二个,依此类推。

示例数据库表:

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')

我先得到最新的回复。如何重新排序查询集,以便来自最新的唯一响应者的所有响应在查询集中首先分组,来自第二个唯一响应者的所有响应都在第二个分组,等等?

4

1 回答 1

0

使用排序()

sorted()让我们首先考虑使用良好的旧函数在 Python 中进行排序。它是一种比较排序,即它通过成对比较项目进行排序,一次一对,并为每一对决定哪一个应该先出现。比较排序仅在比较器(作为排序参数给出的函数)定义了总顺序时才有效:

  1. 如果 a ≤ b 且 b ≤ a 则 a = b (反对称,实际上对于比较排序不是必需的);
  2. 如果 a ≤ b 且 b ≤ c 则 a ≤ c(传递性);
  3. a ≤ b 或 b ≤ a(总数)。

因此,如果您可以定义一个比较器,它从表中获取两行并决定哪一行先行,并且该比较器定义了总顺序,那么您可以sorted使用该比较器进行调用。

但是对于您的问题,这样的比较器根本不存在。当两个不同的用户只考虑两行时,你永远不知道应该先出现哪一行。您将始终需要知道这些作者的最新帖子。底线:你不能使用sorted()

使用 SQL

我不知道 SQL 是否可以处理这个问题。尝试重写您的问题,仅使用您拥有的表格,省略所有 Django 和 Python 内容。如果您创建这样的问题,请添加从该问题到该问题的链接。如果 SQL 可以处理它,那么您可以调用Responses.objects.sql().

使用存储桶

下面的代码是如何使用存储桶按您想要的方式排序的示例。我使用了一个虚拟类 Response,专注于原则。

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
于 2012-06-18T21:27:11.923 回答