我希望用户能够使用javascript在表格中订购对象列表。然后,在django函数中,我想基于相同的顺序对这些对象进行排序,而不是基于属性。
有可能吗?我正在考虑将pk的列表从模板传递到视图,然后根据此列表对对象进行排序,但我还没有找到方法来实现它。
答案 0 :(得分: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和模型实例对象之间的映射。为了制作字典,我使用了dictionary comprehension。
如果要省略已删除的对象:
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]
答案 1 :(得分:1)
我之前必须解决这个问题。
如果您希望用户能够将其重新排序为用户定义的顺序,您可以轻松定义一个字段来存储此订单。
正如您所说,最初,您可以根据id
或upload_date
DateTimeField按顺序提供服务。但您也可以在模型中使用名为position
或order
的{{3}}来表示用户定义的顺序。
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')
这就是我们设法做到的方式。如果您对此方法有更具体的问题,请随时在评论中提问。
修改强>
如果同一个对象可以是许多不同组或列表的成员,并且您希望在该列表中存储成员资格的位置,则可以使用PositiveIntegerField来实现此目的。当您需要存储与两个相关对象之间的关系相关的数据时,直通模型很有用。除了上面显示的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
答案 2 :(得分: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))