【问题标题】:django saving list of foreignkey objects to m2m field w/ through model with orderingdjango通过模型将外键对象列表保存到m2m字段
【发布时间】:2016-09-03 13:39:10
【问题描述】:

我有一个带有 javascript 的 html 表,它允许对通过 POST 表单传递 track_id 列表和行顺序列表的行进行排序。

我刚刚为模型添加了使用 through 的类 PlaylistTrack,因此我可以将排序添加到 tracking.m2m 字段。在我添加直通模型之前,我在下面的视图有效,但现在我不确定如何保存轨道及其相关订单号的 list,因为我不能使用 add() 和我必须使用 create()。我应该如何在我的视图中使用 create() 来保存 track_id 的列表并将订单号与列表相关联?我可以使用 bulk_create 吗?

models.py:

class Playlist(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
    name = models.CharField(max_length=50)
    tracks = models.ManyToManyField(Track, through='PlaylistTrack')

    def __str__(self):
        return self.name

class PlaylistTrack(models.Model):
    track = models.ForeignKey(Track)
    playlist = models.ForeignKey(Playlist)
    order = models.PositiveIntegerField()

    class Meta:
        ordering = ['order']

views.py:

def add_track(request):
    active_playlist = Playlist.objects.get(id=request.POST.get('playlist_id'))
    add_tracks = request.POST.getlist('track_id')
    if request.POST.get('playlist_id'):
        active_playlist.tracks.add(*add_tracks) # how to use create or bulk_create?
    return redirect("playlists:list_playlists")

【问题讨论】:

    标签: django model manytomanyfield


    【解决方案1】:

    Ozgur 的回答基本上涵盖了您。但是,您不需要从数据库中获取PlaylistTrack 实例,您可以使用bulk_create

    def add_track(request):
        playlist_id = request.POST.get('playlist_id')
        track_ids = enumerate(request.POST.getlist('track_id'), start=1)
        PlaylistTrack.objects.bulk_create([
            PlaylistTrack(playlist_id=playlist_id, track_id=track_id, order=i) 
                for i, track_id in track_ids
        ])
        return redirect("playlists:list_playlists")
    

    这将整个过程简化为单个 db 操作,您之前有 (1 + 2n) 操作(n 是轨道数)。

    【讨论】:

    • 谢谢,这同样有效,但我对此行有疑问.. PlaylistTrack(playlist_id=playlist_id, track_id=track_id, order=i), 你怎么使用 playlist_id= 和 track_id= when我的 PlaylistTrack 模型有播放列表和曲目字段名称吗? Django 知道附加 _id 是指模型的 id 字段吗?
    • 是的,对于每一个ForeignKey,django 会自动添加一个同名字段并附加_id,它保存着实际的外键,即相关对象的主键(见@987654321 @)。
    【解决方案2】:

    您需要获取将要添加的Track 对象:

    Track.objects.filter(pk__in=add_tracks)
    

    --

    由于必须填充 order 字段,因此您不能在 M2M 字段上使用 .add()。您必须自己创建对象:

    def add_track(request):
        playlist = Playlist.objects.get(id=request.POST.get('playlist_id'))
        for i, track_id in enumerate(request.POST.getlist('track_id'), start=1):
            track = Track.objects.get(pk=track_id)
            PlaylistTrack.objects.create(track=track, playlist=playlist, order=i)
        return redirect("playlists:list_playlists")
    

    【讨论】:

    • 忘了提到 add() 给了我这个回溯错误:不能在指定中间模型的 ManyToManyField 上使用 add()。请改用 playlists.PlaylistTrack 的管理器。
    猜你喜欢
    • 2019-08-09
    • 1970-01-01
    • 1970-01-01
    • 2015-06-03
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    • 2013-01-20
    • 1970-01-01
    相关资源
    最近更新 更多