【问题标题】:Getting one to many result获得一对多结果
【发布时间】:2020-08-22 06:25:51
【问题描述】:

我在我的 django 查询中做了一些试验和错误。我正在尝试获取一个字段,其旁边有一列值,其中包含元素列表。基本上我想弄清楚如何获得这个结果:

{
  feed: {},
  [{
   id: 1,
   media_id: 11
  }, {
   id: 2,
   media_id: 22
  }]
}

我在 python shell 中尝试了这个查询,它给了我这个结果:

>>> query = Feed.objects.filter(Q(feedmedia__isnull=True)|Q(feedmedia__isnull=False)).values('message','feedmedia__id','feedmedia__media_id').distinct()

>>> print(query)


<FeedQuerySet [{'message': 'Classic motorcycles <3', 'feedmedia__id': 145, 'feedmedia__media_id': 152}, {'message': 'sample video', 'feedmedia__id': 147, 'feedmedia__media_id': 153}, {'message': 'Classic motorcycles <3', 'feedmedia__id': 146, 'feedmedia__media_id': 151}]>

关于结果,我了解为什么包含“消息”(Feed 表中的字段之一),问题是我不知道如何排除它以获得所需的输出.

以下是此次操作涉及的三个模型:

class Media(models.Model):
   original_url = models.CharField(max_length=200, null=False, unique=False)
   small_url = models.CharField(max_length=200, null=True, unique=False)
   medium_url = models.CharField(max_length=200, null=True, unique=False)
   large_url = models.CharField(max_length=200, null=True, unique=False)
   uploaded_at = models.DateTimeField(auto_now_add=True)

   class Meta:
     db_table = "media"


class Feed(models.Model):
   message = models.CharField(max_length=3000, null=True, unique=False)
   type = models.CharField(max_length=50, null=False, unique=False)
   category = models.CharField(max_length=50, null=False, unique=False)
   priority_level = models.IntegerField(default=0, null=False, unique=False)
   origin_location = models.CharField(max_length=100, null=True, unique=False)
   created_at = models.DateTimeField(auto_now_add=True)

   objects = FeedManager()

   class Meta:
     db_table = 'feed'


# Junction Table for Feed and Media
class FeedMedia(models.Model):
"""Model to represent gosam posts/feeds."""

   media = models.ForeignKey(Media, on_delete=models.CASCADE, null=False)
   feed = models.ForeignKey(Feed, on_delete=models.CASCADE, null=False)
   creator = models.ForeignKey(Profile, on_delete=models.CASCADE, null=False)

   objects = FeedMediaManager()

   class Meta:
     db_table = 'feed_media'

【问题讨论】:

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


    【解决方案1】:

    您没有在FeedMediaForeignKey 字段中定义自定义related_name

    因此,您的默认反向关系访问器将是 &lt;model_name&gt;_set,例如feedmedia_set.

    因此,如果您想通过FeedMediaFeed 访问Media 对象,则如下:

    query = Feed.objects.filter(Q(feedmedia_set__isnull=True)|Q(feedmedia_set__isnull=False)).values('message','feedmedia_set__id','feedmedia_set__media_id').distinct()
    

    【讨论】:

    • 它会抛出一个错误:“Cannot resolve keyword 'feedmedia_set' into field”。
    【解决方案2】:

    如果您使用的是django rest framework,那么只需像这样创建一个序列化程序:

    class FeedMediaSerializer(serializer.ModelSerializer):
        class Meta:
           model = FeedMedia
           fields = ["id", "media_id"]
    
    
    class FeedSerializer(serializer.ModelSerializer):
        media = FeedMediaSerializer(source="feedmedia", read_only=True)
    
        class Meta:
            model = Feed
            fields = ["message", "media"]
    

    并尝试像这样的 Python shell:

    >> query = Feed.objects.filter(Q(feedmedia__isnull=True)|Q(feedmedia__isnull=False))
    >> FeedSerializer(query, many=True).data
    

    【讨论】:

    • 还是和我上面的结果一样,唯一的区别是结果是用 OrderedDict 组成的
    • 我认为它们不会相同。因为在这里你应该得到 JSON 输出,消息作为单个字符串,媒体作为 JSON 的每个项目中的列表
    【解决方案3】:

    您可以为每个模型编写序列化程序,然后设置您要使用的特定字段

    class FeedSerializer(serializers.ModelSerializer):
       class Meta:
           model = Fedd
           fields = '__all__' # for all fields
           fields = ('field_1', 'field_1', 'field_1') # for specific fields
    

    然后在 apiviews 中

    class MyFilterView(APIView):
        def get(self, request)
             filter_data = Feed.objects.filter()#your filter
             serializer = FeedSerializer(filter_data, many=True) # many=True if are many results
             return Response(serializer.data)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-16
      • 1970-01-01
      • 2015-12-16
      • 2013-11-05
      • 2014-02-08
      • 1970-01-01
      • 2018-11-09
      相关资源
      最近更新 更多