簡體   English   中英

檢索Django中通用外鍵關系的“多”結尾

[英]retrieving the 'many' end of a Generic Foreign Key relationship in Django

在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_idpage_content_objectpage_content_type是與報告的page_object_id關系

目前,顯示所有節點(這是一個錯誤)。

在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這個問題很明顯,讓我相信這是一個結構性問題)

執行查詢時

well.nodes.all()

這將通過您在模型中描述的關系獲取與well相關的所有節點。

聽起來好像要通過page_content_object通用外鍵關系將返回的節點限制為引用Report對象r的節點。 是對的嗎? 如果是,則需要顯式過濾節點,如下所示:

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模型上添加一個方法。

Ticker報告有很多Wells,這些Wells在所有Ticker報告中共享。 不同的是你可以將節點綁定到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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM