19

在 Django 中,当我请求具有多对多关系的资源时,我最终会获得关系的子部分中的所有项目,即使是那些与父级没有直接关系的项目。如果我向您展示代码会更容易(精简类以仅显示必要的内容):

楷模

class Report(models.Model):
    name = models.CharField(max_length=255)
    slug = AutoSlugField(_('slug'), populate_from='name')
    wells = models.ManyToManyField(Well, null=True)
    uuid = UUIDField(editable=False, blank=True, version=4, unique=True)


class Well(models.Model):
    slug = AutoSlugField(_('slug'), populate_from='name')
    name = models.CharField(max_length=255)

class Node(models.Model):
    @property
    def well(self):
        raise NotImplementedError("The 'well' field must be implemented")
    //irrelevant GFK omitted
    page_content_type = models.ForeignKey(ContentType, null=True, blank=True, related_name='page')
    page_object_id = models.PositiveIntegerField(blank=True, null=True)
    page_content_object = generic.GenericForeignKey('page_content_type', 
     'page_object_id')

资源

class ReportResource(ModelResource):
    wells = fields.ManyToManyField(WellResource, 'wells', full=True)
    stock = fields.ForeignKey(TickerResource, 'stock', full=True)

    class Meta:
        queryset = Report.objects.all()
        resource_name = 'ticker_reports'

class WellResource(ModelResource):
    nodes = fields.ToManyField('wells.api.NodeResource', 'nodes', full=True)
    type = fields.ForeignKey(WellTypeResource, 'type', full=True)

    class Meta:
        queryset = Well.objects.all()
        resource_name = 'wells'

class NodeResource(ModelResource):
    order = fields.IntegerField()
    content_object = GenericForeignKeyField({
                                                Content: UUIDOnlyContentResource
                                            }, 'content_object', full=True)

    class Meta:
        queryset = Node.objects.all()
        resource_name = 'nodes'
        filtering = {
            'ticker_report': ALL_WITH_RELATIONS
        }

一个 Ticker Report 有许多 Wells,这些 Wells 在所有 Ticker Reports 中共享。不同的是你可以将 Nodes 绑定到 Wells;对于给定的代码报告,应该显示的唯一节点是与该代码报告相关的节点。

因此,对于给定的股票报告和一组井,只应显示与该股票报告共享该 GenericForeignKey 的节点。

关系:

page_object_id, page_content_object,page_content_type是与 Report 的 GenericForeignKey 关系

目前,显示所有节点(这是一个错误)。

在 TastyPie 中,我如何告诉它只显示相关对象而不是所有对象?

这是一个简短的 python 控制台,更简洁地显示了问题:

>>> r = Report.objects.get(id=1)                                                                                                        
>>> for well in r.wells.all():                                                                                                          
...     for node in well.nodes.all():                                                                                                   
...         print 'Node in Well {0} is {1}'.format(well, node)                                                                          
...                                                                                                                                     
Node in Well The Areas You Must Watch (the-areas-you-must-watch - Fancy List) is Apple Content #1:Apple (0)                             
Node in Well The Areas You Must Watch (the-areas-you-must-watch - Fancy List) is First Solar Content #1:first solar (0)                 
Node in Well Risks (risks - Headline and Lead) is Apple Content #2:Apple (0)                                                            
Node in Well Risks (risks - Headline and Lead) is First Solar Content #2:first solar (0)                                                
>>> 

SQL 实际输出

SELECT node.id, node.uuid, node.order,node.content_type_id, node.object_id,
       node.page_content_type_id, node.page_object_id, node.well_id FROM node 
WHERE node.well_id = 1  
ORDER BY node.order ASC 

(已修改以使其更易于阅读)

预期的 SQL 输出:

SELECT node.id, node.uuid, node.order,node.content_type_id, node.object_id,
       node.page_content_type_id, node.page_object_id, node.well_id FROM node 
WHERE node.well_id = 1  AND node.page_content_type_id = 99 /*Report Content TypeID */ AND node.page_content_object_id = 1 /*ReportID*/
ORDER BY node.order ASC 

预期输出:

Node in Well The Areas You Must Watch is Apple Content #1
Node in Well Risks is Apple Content #2:Apple (0)

如何过滤掉与 Django 和 TastyPie 的多对多关系的子端(尽管这个问题在没有 TastyPie 的情况下也很明显,让我相信这是一个结构性问题)

4

2 回答 2

5

执行查询时

well.nodes.all()

这会通过您在模型中描述的关系获取所有相关的节点。well

听起来好像您想将返回的节点限制为通过通用外键关系引用Report对象的节点。是对的吗?如果是,那么您需要显式过滤节点,如下所示:rpage_content_object

r = Report.objects.get(id=1)
for well in r.wells.all():                                                                                                          
    for node in well.nodes.filter(page_object_id = r.id,
                                  page_content_type = ContentType.objects.get_for_model(r)):
        # ...

更新:我对 TastyPie 一无所知,我不得不说我不太了解您要做什么,但是在 Django 中,如果井和节点之间存在关系,那么您需要将其添加到你的模型。例如,如果每个都Node恰好属于一个Well,那么很自然的做法就是在模型中添加一个字段Node

class Node(models.Model):
    # ...
    well = models.ForeignKey('Well')

然后如果你想找到属于属于特定Report对象的井的所有节点r,所述节点也r通过通用外键关系引用,你会发出查询:

 Node.objects.filter(well__report = r,
                     page_object_id = r.id,
                     page_content_type = ContentType.objects.get_for_model(r))

如果您必须经常这样做,那么很自然的事情就是在Report模型上添加一个方法。

于 2013-04-01T13:16:15.783 回答
1

一个 Ticker Report 有许多 Wells,这些 Wells 在所有 Ticker Reports 中共享。不同的是你可以将 Nodes 绑定到 Wells;对于给定的代码报告,应该显示的唯一节点是与该代码报告相关的节点。

在 Django 中,当我请求具有多对多关系的资源时,我最终会获得关系的子部分中的所有项目,即使是那些与父级没有直接关系的项目。如果我向您展示代码会更容易(精简类以仅显示必要的内容):

如果我理解正确,该节点可以与报告或井相关(因为您提到与该 Ticke Report 相关)。您正在寻找与报告相关的节点,而不是与报告的井相关的节点。(因为您正在寻找与父级直接相关的节点(报告?))

如果我是正确的,这很简单:

https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#reverse-generic-relations

class Report(models.Model):
    name = models.CharField(max_length=255)
    slug = AutoSlugField(_('slug'), populate_from='name')
    wells = models.ManyToManyField(Well, null=True)
    uuid = UUIDField(editable=False, blank=True, version=4, unique=True)

    nodes = generic.GenericRelation(Node)


# usage
r = Report.objects.get(id=1)
nodes = r.nodes.all()
于 2013-04-04T02:06:34.613 回答