在Django中重组多对多关系

3 投票
3 回答
602 浏览
提问于 2025-04-15 23:03

我在我的模型中有一个多对多的关系,现在想在我的某个页面上重新组织一下这些信息。

我的网站上有视频。在每个视频的页面上,我想列出出现在这个视频中的演员,并且给每个演员添加链接,点击后可以直接跳到他们在视频中出现的部分(这些链接会直接跳到视频的那个时间点)。

下面是一个示例:


这里嵌入了一个Flash视频

演员名单...

Ted smith: 1:25, 5:30
jon jones: 5:00, 2:00

这是我模型中相关的部分

class Video(models.Model):
    actor = models.ManyToManyField( Actor, through='Actor_Video' )
    # more stuff removed

class Actor_Video(models.Model):
    actor = models.ForeignKey( Actor )
    video = models.ForeignKey( Video)
    time = models.IntegerField()

这是我的Actor_Video表的样子,可能这样更容易理解我在做什么。

id     actor_id    video_id    time (in seconds)
1        1             3        34
2        1             3        90

我觉得我需要在视图中重新组织这些信息,但我搞不清楚怎么做。用Django的ORM在模板中似乎无法实现。我尝试过创建字典和列表,但都没有成功。任何帮助都非常感谢。谢谢。

3 个回答

0

我建议把你的逻辑放在视图函数里,而不是模板中。如果我理解得没错的话,每个页面上只有一个视频,这样事情就简单多了。

def video_view(request,video_id)
    video = Video.objects.get(pk=video_id)
    actors = Actor.objects.filter(video=video)
    #now add a custom property to each actor called times
    #which represents a sorted list of times they appear in this video
    for actor in actors:
        actor.times = [at.time for at in actor.actor_video_set.filter(video=video).order_by('time')] #check syntax here

然后在模板中,你可以直接循环遍历 actor.times:

<ul>
{% for actor in video.actors.all.distinct %}
    <li>{{ actor }}:

        <ul>
    {% for t in actor.times %} #this now returns only the times corresponding to this actor/video
            <li><a href="?time={{ t.time }}">{{ t.time }}</a></li> #these are now sorted

注意 - 这里的代码都是我没有用开发工具写的,你需要检查一下语法。希望这能帮到你!

额外提示:可以定义一个 times(video) 函数,作为 Actor 模型类的自定义函数。

1

我觉得在Django中,最符合它风格的做法是使用“regroup”这个模板标签:

{% regroup video.actor_video_set.all by actor as video_times %}
{% for actor_times in video_times %}
    <li>{{ actor_times.grouper }}: # this will output the actor's name
    {% for time in actor_times %}
        <li>{{ time }}</li> # this will output the time
    {% endfor %}
    </li>
{% endfor %}

这样你就可以避免在模板中使用过多的逻辑。顺便说一下,你可以在这里了解关于regroup标签的更多信息。

0

我把它整理成了一个包含时间列表的字典

actor_sets = data['video'].video_actor_set.all()
data['actors'] = {}

for actor_set in actor_sets:
    if not data['actors'].has_key( actor_set.actor ):
        data['actors'][actor_set.actor] = []
        data['actors'][actor_set.actor].append( actor_set.time )

然后在模板中,我遍历这个字典,而不是在实际模板中直接运行查询

撰写回答