ユーザーが 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
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')
それが私たちがそれを成し遂げた方法です。このアプローチに関して具体的な質問がある場合は、コメントでお気軽にお問い合わせください。
編集:
同じオブジェクトが多くの異なるグループまたはリストのメンバーになる可能性があり、そのリスト内のメンバーシップの位置を保存する場合は、スルー モデルを使用してこれを実現できます。スルー モデルは、関連する 2 つのオブジェクト間の関係に関連するデータを格納する必要がある場合に役立ちます。上記のクラスに加えて、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))