【问题标题】:How do I return a list in a Django Annotation?如何在 Django 注释中返回列表?
【发布时间】:2020-03-31 07:39:10
【问题描述】:

现在我有以下,非常慢但有效的代码:

crossover_list = {}
    for song_id in song_ids:
        crossover_set = list(dance_occurrences.filter(
            song_id=song_id).values_list('dance_name_id', flat=True).distinct())
        crossover_list[song_id] = crossover_set

它返回一个字典,其中歌曲 ID 用作字典键,整数值列表用作值。前三个键如下:

crossover_list = {
        1:[38,37],
        2:[38],
        ....
}

这里有没有人知道将其包装成单个查询的简洁方法?数据存在于具有三列的单个表中,其中每个 song_id 可以与多个 dance_id 相关联。

song_id | playlist_id | dance_id
      1             1         38
      1             2         37
      2             1         38

理想情况下,我想弄清楚如何返回是:

<QuerySet[{'song_id':1, [{'dance_id':38, 'dance_id':37}]}, {'song_id':2, [{'dance_id':38}]}]>

感谢任何想法或帮助。

编辑:根据要求,这里是有问题的模型:

# This model helps us do analysis on music/dance crossover density, song popularity within-genre,
# playlist viability within-genre (based on song occurrence counts per song within each playlist), etc.
class SongOccurrences(models.Model):
    song = models.ForeignKey(
        'Songs',
        on_delete=models.CASCADE,
    )
    playlist = models.ForeignKey(
        'Playlists',
        on_delete=models.CASCADE,
    )

    dance_name = models.ForeignKey(
        'DanceMasterTable',
        on_delete=models.CASCADE,
    )

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['song', 'playlist'], name='unique occurrence')
        ]

# This model contains relevant data from Spotify about each playlist
class Playlists(models.Model):
    spotify_playlist_uri = models.CharField(max_length=200, unique=True)
    spotify_playlist_owner = models.CharField(max_length=200)
    spotify_playlist_name = models.CharField(max_length=200)
    current_song_count = models.IntegerField()
    previous_song_count = models.IntegerField()
    dance_name = models.ForeignKey(
        'DanceMasterTable',
        on_delete=models.CASCADE,
    )

# This model contains all relavent data from Spotify about each song
class Songs(models.Model):
    title = models.CharField(max_length=200)
    first_artist = models.CharField(max_length=200)
    all_artists = models.CharField(max_length=200)
    album = models.CharField(max_length=200)
    release_date = models.DateField('Release Date', blank=True)
    genres = models.CharField(max_length=1000, blank=True)
    popularity = models.FloatField(blank=True)  # This value changes often
    explicit = models.BooleanField(blank=True)
    uri = models.CharField(max_length=200, unique=True)
    tempo = models.FloatField(blank=True)
    time_signature = models.IntegerField()
    energy = models.FloatField(blank=True)
    danceability = models.FloatField(blank=True)
    duration_ms = models.IntegerField()
    tonic = models.IntegerField(blank=True)
    mode = models.IntegerField(blank=True)
    acousticness = models.FloatField(blank=True)
    instrumentalness = models.FloatField(blank=True)
    liveness = models.FloatField(blank=True)
    loudness = models.FloatField(blank=True)
    speechiness = models.FloatField(blank=True)
    valence = models.FloatField(blank=True)

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['title', 'first_artist', 'all_artists'], name='unique song')
        ]

# This model contains the (static) master list of partner dances to be analyzed.
class DanceMasterTable(models.Model):
    dance_name = models.CharField(max_length=200, unique=True)

【问题讨论】:

  • 我怀疑你想要prefetch_related。但是展示你的模型。

标签: django django-queryset annotate


【解决方案1】:

您正在循环中运行查询,因此速度很慢。

您可以事先按所有song_ids 过滤dance_occurrences,最后循环这些值以将舞蹈ID 附加到它们各自的歌曲ID。

示例

song_dance_occurrences = dance_occurrences.filter(
    song_id__in=song_ids
).values_list('song_id', 'dance_id').distinct()

crossover_dict = {}
for song_id, dance_id in song_dance_occurrences:
    crossover_dict[song_id] = crossover_dict.get(song_id, [])
    crossover_dict[song_id].append(dance_id)

【讨论】:

  • 这有帮助!我试图对您的回复进行投票,但我没有足够的声誉点让 Stackoverflow 注册它。我唯一需要添加的是 .distinct() 到 song_dance_occurrences 查询中,以获得我正在寻找的确切输出。谢谢!
  • 更新了答案。如果有效,您可以接受答案。
猜你喜欢
  • 2012-07-02
  • 2021-12-26
  • 1970-01-01
  • 2021-08-03
  • 1970-01-01
  • 2019-10-01
  • 2019-05-09
  • 2013-07-21
  • 2022-01-12
相关资源
最近更新 更多