在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报告有很多Wells,这些Wells在所有Ticker报告中共享。不同的是你可以将节点绑定到Wells;对于给定的股票报告,应显示的唯一节点是与该股票报告相关的节点。
因此,对于给定的股票报告和一组井,只应显示与该Ticker报告共享该GenericForeignKey的节点。
关系:
page_object_id
,page_content_object
,page_content_type
是与报告的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)
>>>
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
(修改后更容易阅读)
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这个问题很明显,让我相信这是一个结构性问题)
答案 0 :(得分:5)
执行查询时
well.nodes.all()
通过您在模型中描述的关系获取与well
相关的所有节点。
听起来好像要通过Report
通用外键关系将返回的节点限制为引用r
对象page_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
模型上添加一个方法。
答案 1 :(得分:1)
Ticker报告有很多Wells,这些Wells在所有人之间共享 股票报告。不同的是你可以将节点绑定到Wells; 对于给定的股票报告,应该显示的唯一节点是 那些与该股票报告相关的信息。
在Django中,当我请求具有多对多的资源时 关系,我最终得到了孩子的所有项目 关系,即使那些与父母没有直接关系的关系。这将是 如果我向您展示代码(修剪为仅显示的类)会更容易 什么是必要的):
如果我理解正确,该节点可以与报告或井相关(因为您提到与该Ticke报告相关)。 您正在寻找与报告相关的节点,而不是与报告的井相关的节点。 (因为您正在寻找与父母直接相关的节点(报告?))
如果我没错,那很简单:
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()