【问题标题】:Django Rest returning related items for each itemDjango Rest为每个项目返回相关项目
【发布时间】:2021-01-15 19:14:47
【问题描述】:

我试图在类似的问题中找到答案,但没有一个符合我的期望。

我有 2 个模型:

class Artist(models.Model):
    name = models.CharField(max_length=255)
    music_type = models.CharField(max_lenght=50)

    def __str__(self):
        return self.name

class Event(models.Model):
    event_name = models.CharField(max_length=255)
    ...
    artists = models.ManyToManyField(Artist)

    def __str__(self):
        return self.event_name

我也有serializers.py文件:

class EventSerializer(serializers.ModelSerializer):

    class Meta:
        model = Event
        fields = '__all__'


class ArtistSerializer(serializers.ModelSerializer):
    events = EventSerializer(source='event_set', many=True)

    class Meta:
        model = Artist
        fields ='__all__'

ArtistSerializer 中的 event 允许我返回艺术家参与的所有活动。 现在,对于每个艺术家,如果他们曾经参加过同一活动,我想获取所有艺术家的列表。

例如,我有 5 个艺术家 (A1...A5) 和 3 个事件 (E1...E3) 在事件 1 中:[A1,A3]

在事件 2 中:[A3,A4,A5,A2]

在事件 3 中:[A2,A3]

So for A3 I would like to get list [A1,A4,A5,A2]
For A1: [A3]
For A2: [A3,A4,A5]

不幸的是,我在创建这个查询时遇到了很大的问题,因为 SQL 查询和 ORM 机制在这种情况下看起来更加复杂。有人可以帮我解决这个问题或给出解决方法的提示吗?

如果需要,我会分享更多代码

【问题讨论】:

    标签: django-models django-rest-framework django-queryset


    【解决方案1】:

    您可以查询直通模型以获取与事件相关的艺术家。这是 django 为建立 M2M 关系而创建的中间模型。

    如果您有 ManyToManyField,它的属性为 through,即 M2M 模型。

    因此,从您的事件模型中,您可以执行 Event.artists.through.objects.all() 之类的操作,您会看到 M2M 模型中的所有实例。

    因此,要找出与给定事件相关联的艺术家,您可以查询同一张表;

    Event.artists.through.objects.filter(event_id=1).select_related('artist')

    这将返回 M2M 中属于事件 1 的所有对象。然后您可以从那里获取艺术家,或者直接获取艺术家 ID Event.artists.through.objects.filter(event_id=1).values_list('artist_id, flat=True)

    鉴于您评论中的场景...

    如果您有艺术家,则可以运行查询以获取他们参加过的活动,然后使用这些活动 ID 运行另一个查询。然后,在第二个查询中,您希望获取不是您正在查看的当前艺术家的艺术家 ID。

    # First get the events that the current artist has been in
    event_ids = Event.artists.through.objects.filter(artist_id=1).values_list('event_id, flat=True)
    
    # Then get the other artists who have been in the same events
    other_artist_ids = Event.artists.through.objects.filter(event_id__in =event_ids).exclude(artist_id=1).values_list('artist_id, flat=True)
    
    # or the full instances
    other_artists = Event.artists.through.objects.filter(event_id__in =event_ids).exclude(artist_id=1).select_related('artist')
    

    【讨论】:

    • 嗯,我有返回事件的端点以及属于该事件的所有艺术家。现在对于每个艺术家,如果他们曾经一起参加过任何活动,我想获取其他艺术家的列表。 Tbh 这对我来说有点复杂。如果我能很好地理解您的回答,我必须遍历每个事件,让所有艺术家找到解决方案,如果他们在其他事件中不重复他们?
    • 我试图展示该场景的示例
    • 好吧,所以我正在测试这个,它适用于硬编码的 Artist_id=1。我还必须将 other_artist_ids 查询设置为“设置”以不返回重复项。我还有另一个问题 - 将这些数据作为 JSON 返回的最佳方式是什么?获取所有事件的ID,迭代并更改artist_id 并执行第二个查询?还是这样做是更好的选择?
    • 您应该能够覆盖端点上的查询集以从请求中获取数据,以便您可以使其动态工作。
    • 我想我仍然不知道 django rest 可以很好地处理这个解决方案。你能看看我在 github 上的项目吗? github.com/f4lco0n/grywit_task - 上面的查询没有更新视图
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-05
    • 2021-03-19
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    相关资源
    最近更新 更多