2

我希望用户能够使用 javascript 对表中的对象列表进行排序。然后,在 django 函数中,我想根据相同的顺序对这些对象进行排序,而不是根据属性。

是否可以?我正在考虑将 pk 列表从模板传递到视图,然后根据此列表对对象进行排序,但我还没有找到方法。

在此处输入图像描述

4

3 回答 3

2

我认为这对于查询集是不可能的。尝试以下操作:

pk_list = [2, 1, 3, 4]
pk2obj = {obj.pk: obj for obj in Model.objects.all()}
objects_ordered = [pk2obj[pk] for pk in pk_list]

pkg2obj是pk和模型实例对象之间的映射。为了制作字典,我使用了字典理解

如果要省略已删除的对象:

objects_ordered = [pk2obj[pk] for pk in pk_list if pk in pk2obj]

否则,如果您想用默认值替换已删除的对象(None在以下代码中):

objects_ordered = [pk2obj.get(pk, None) for pk in pk_list]
于 2013-08-13T14:53:30.077 回答
1

我以前必须解决这个确切的问题。

如果您希望用户能够将它们重新排序为用户定义的订单,您可以轻松定义一个字段来存储此订单。

正如您所说,最初,您可以根据idupload_date DateTimeField为它们提供服务。但是您也可以在模型中有一个PositiveIntegerField,命名为positionor order,以表示用户定义的顺序。

class MediaItem(models.Model):
    user = models.ForeignKey(User)
    upload_date = models.DateTimeField(auto_now_add = True)
    position = models.PositiveIntegerField()

每当用户在前端更改订单时,JS 可以将新订单作为对象数组(即 . new_order = [{"pk":3, "position":1}, {"pk":1, "position":2}, {"pk":2, "position":3}])发送。视图可以通过 查找每个实例pk,并更改position

for obj in new_order:
    media_item = MediaItem.objects.get(pk=obj['pk'])
    media_item.position = obj['position']
    media_item.save()

然后总是使用查询

objects_ordered.objects.order_by('position')

这就是我们设法做到的方式。如果您对此方法有更具体的问题,请随时在评论中提问。

编辑:

如果同一个对象可以是许多不同组或列表的成员,并且您希望在该列表中存储成员资格的位置,则可以使用through 模型来实现。当您需要存储与两个相关对象之间的关系相关的数据时,直通模型非常有用。除了MediaItem上面显示的类之外,这是您的其他模型的样子:

class Album(models.Model):
    media_items = models.ManyToManyField(MediaItem,
                                         related_name = 'album_media_items',
                                         through = 'Membership')

class Membership(models.Model):
    album = models.ForeignKey(Album,
                              related_name = 'album')
    media_item = models.ForeignKey(MediaItem,
                                   related_name = 'media_item')
    date = models.DateTimeField(auto_now_add = True)
    position = models.PositiveIntegerField()

然后,您可以查询Membership实例,而不是MediaItem实例。

# get id of list, or album...
alb = Album.objects.get(pk=id_of_album)
media_items = Membership.objects.filter(album=alb).order_by('position')
for item in media_items:
    # return the items, or do whatever...
    # keep in mind they are now in the user-defined order
于 2013-08-13T15:21:46.290 回答
1

你可以这样做:

pk_list = [1,5,3,9]

foo = Foo.objects.filter(id__in=pk_list)

#Order your QuerySet in base of your pk_list using Lambda

order_foo = sorted(foo, key = lambda:x , pk_list.index(x.pk))
于 2014-09-17T14:32:58.760 回答