多对多查询(Django)

1 投票
1 回答
953 浏览
提问于 2025-04-18 17:28

我想知道怎么通过一个多对多的字段来查询一个艺术家参加过的演出,并且列出这些演出的类型(已经完成的)。我对Django还比较陌生,刚刚完成了Tango with Django的教程,不过我现在有的代码如下。

models.py

class Genre(models.Model):
  name = models.CharField(max_length=20, unique=True, blank=False)

  def __unicode__(self):
    return self.name


class Artist(models.Model):
  name = models.CharField(max_length=50, unique=True, blank=False)
  photo = models.ImageField(upload_to='artist_photos', blank=True)
  logo = models.ImageField(upload_to='artist_logos', blank=True)
  genre = models.ManyToManyField(Genre)
  twitter = models.URLField(blank=True)
  facebook = models.URLField(blank=True)
  instagram = models.URLField(blank=True)

  def __unicode__(self):
    return self.name

class Venue(models.Model):
  name = models.CharField(max_length=50, unique=True, blank=False)
  logo = models.ImageField(upload_to='venue_logos', blank=True)
  capacity = models.IntegerField(blank=False)
  address = models.CharField(max_length=50, blank=True)
  city = models.CharField(max_length=50, blank=True)
  state = models.CharField(max_length=50, blank=True)
  zip_code = models.IntegerField(max_length=50, blank=True, null=True)
  website = models.URLField(blank=True)
  twitter = models.URLField(blank=True)
  facebook = models.URLField(blank=True)
  instagram = models.URLField(blank=True)

  def __unicode__(self):
    return self.name

class Show(models.Model):
  venue = models.ForeignKey(Venue)
  date_time = models.DateTimeField(blank=False)
  attendance = models.IntegerField(blank=False)
  bands = models.ManyToManyField(Artist)

views.py

def artists(request):
  context = RequestContext(request)
  artists = Artist.objects.order_by('name')
  shows = Show.objects.order_by('-date_time')
  # artist_shows = Show.objects.filter(????????)

context_dic = {'artists': artists, 'shows': shows}

return render_to_response('artistdb/artists.html', context_dic, context)

artist.html

<h2>Artists</h2>
{% if artists %}
    <ul>
        {% for artist in artists %}
            <li>{{ artist.name }}<br />
                <ul>
                {% for g in artist.genre.all %}
                    <li>{{ g.name }}</li>
                    {% endfor %}
                </ul>
            </li>
            <br />
        {% endfor %}
    </ul>   
{% else %}
    There are no artist.
{% endif %}     

1 个回答

3

要获取某个艺术家演出的节目,你可以这样做:

artist = Artist.objects.get(name="johndt6")

artist.show_set.all() # Will return all shows related to the artist

建议在你的外键和多对多字段上设置一个 related_name 参数。这样,在节目模型中,艺术家与节目的多对多关系可以写成:

bands = models.ManyToManyField(Artist, related_name="shows")

然后,你可以这样查询艺术家的节目:

artist.shows.all()  # Will return all of the artists shows

如果你愿意,也可以使用普通的查询方式:

shows = Show.objects.filter(bands__in=artist)  # Will return all of an artist's shows

不过,这样的方式没有使用 Django 内置的关系那么方便。

查看文档在这里

撰写回答