django 无法在我的网页上显示ManytoManyField内容

5t7ly7z5  于 2023-07-01  发布在  Go
关注(0)|答案(2)|浏览(128)

访问直通表上的数据列表时遇到问题。直通表称为Cast,它有一个ManyToManyField用于我的Movie表(列出数据库中的每部电影),另一个ManyToManyField用于我的Person表(列出每个演员)。
这些字段必须是ManyToMany,因为一个演员可以出现在许多不同的电影中,而一部电影可以包含许多不同的演员。
我想运行一个for循环,它列出与给定电影相关的所有演员(通过movies主键过滤),并将它们显示在网页上。到目前为止,我无法在网页上列出任何内容(Movie.title显示标题,但我无法显示Cast表中的任何内容)。
我已经尝试阅读所有其他相关的stackoverflow解决方案(如listing objects from ManyToManyField),但我仍然无法让演员的名字显示在网站上。

/Model.py 

class Movie(models.Model):
    title = models.CharField(max_length=250)
    

class Person(models.Model):
    name = models.CharField(max_length=100)

class Cast(models.Model):
    movie = models.ManyToManyField(
        Movie,
    )
    castmember = models.ManyToManyField(
        Person
    )
/View.py

class MoviePageView(TemplateView):
    template_name = '_movie_info.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['movie'] = Movie.objects.all()
        context['cast'] = Cast.objects.filter(movie__id=**kwargs)

I have also tried:
context['cast'] = Cast.objects.filter(movie__id=self.movie.id)
context['cast'] = Cast.objects.filter(movie__id=**kwargs)
context['cast'] = Cast.objects.all()
/URL.py
urlpatterns = urlpatterns = [
    path("<int:pk>", MovieDetailView.as_view(), name="movie_detail"),
]
html page

<div>{{ movie.title }}</div>

{% for info in cast.castmember.all %}
            <div>{{ info.name }}</div>
{% endfor %}
k5ifujac

k5ifujac1#

除非你在中间表中需要额外的字段(我相信这是必要的),你可以使用:
models.py

class Person(models.Model):
    name = models.CharField(max_length=100)

class Movie(models.Model):
    title = models.CharField(max_length=250)
    cast = models.ManyToManyField(Person)

views.py

class MoviePageView(TemplateView):
    template_name = "_movie_info.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        obj = Movie.objects.get(pk=context.get("pk"))
        context["movie"] = obj
        return context

_movie_info.html

...
<body>
    <h2>{{ movie.title }}</h2>
    <p>Cast:</p>
    <ul>
    {% for actor in movie.cast.all %}
        <li>{{ actor.name }}</li>
    {% endfor %}
    </ul>
</body>
...
bwntbbo3

bwntbbo32#

你的Cast模型没有多大意义,它充当一组人,这组人可以被分配给 * 多个 * 电影。
您可以将其建模为:

class Movie(models.Model):
    title = models.CharField(max_length=250)
    cast = models.ManyToManyField('Person', through='Cast')

class Person(models.Model):
    name = models.CharField(max_length=100)

class Cast(models.Model):
    movie = models.ForeignKey(Movie, on_delete=models.CASCADE)
    castmember = models.ForeignKey(Person, on_delete=models.CASCADE)
    role = models.CharField(max_length=128, null=True, default=None)

在这种情况下,Cast充当连接表,您甚至可以为每个Person/movie组合添加role
至于视图,这是一个简单的**DetailView**[Django-doc]:

from django.views.generic import DetailView

class MoviePageView(DetailView):
    model = Movie
    template_name = '_movie_info.html'

这就是我的观点。在模板中,我们可以访问cast:

<div>{{ movie.title }}</div>

{% for person in movie.cast.all %}
    <div>{{ person.name }}</div>
{% endfor %}

我们甚至可以通过预取强制转换来添加角色:

from django.db.models import Prefetch
from django.views.generic import DetailView

class MoviePageView(DetailView):
    model = Movie
    queryset = Movie.objects.prefetch_related(
        Prefetch('cast_set', Cast.objects.select_related('castmember'))
    )
    template_name = '_movie_info.html'

并将其渲染为:

<div>{{ movie.title }}</div>

{% for person in movie.cast_set.all %}
    <div>{{ cast.castmember.name }} as {{ cast.role }}</div>
{% endfor %}

相关问题