我希望用户能够使用 javascript 对表中的对象列表进行排序。然后,在 django 函数中,我想根据相同的顺序对这些对象进行排序,而不是根据属性。
是否可以?我正在考虑将 pk 列表从模板传递到视图,然后根据此列表对对象进行排序,但我还没有找到方法。
我希望用户能够使用 javascript 对表中的对象列表进行排序。然后,在 django 函数中,我想根据相同的顺序对这些对象进行排序,而不是根据属性。
是否可以?我正在考虑将 pk 列表从模板传递到视图,然后根据此列表对对象进行排序,但我还没有找到方法。
我认为这对于查询集是不可能的。尝试以下操作:
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]
我以前必须解决这个确切的问题。
如果您希望用户能够将它们重新排序为用户定义的订单,您可以轻松定义一个字段来存储此订单。
正如您所说,最初,您可以根据id
或upload_date
DateTimeField为它们提供服务。但是您也可以在模型中有一个PositiveIntegerField,命名为position
or 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
你可以这样做:
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))