2012-08-14 46 views
39

我是使用GenericForeignKey的新手,我無法讓它在查詢語句中工作。該表大致如下所示:django:我如何根據GenericForeignKey的字段進行查詢?

class Ticket(models.Model): 
    issue_ct = models.ForeignKey(ContentType, related_name='issue_content_type') 
    issue_id = models.PositiveIntegerField(null=True, blank=True) 
    issue = generic.GenericForeignKey('issue_ct', 'issue_id') 

class Issue(models.Model): 
    scan = models.ForeignKey(Scan) 

的掃描產生一個問題,一個問題產生了一些票,和我做了問題作爲一個外鍵票務表。現在我有一個Scan對象,並且我想查詢與此掃描相關的所有票據。我先試了一下:

tickets = Tickets.objects.filter(issue__scan=scan_obj) 

哪個不行。然後我試過這個:

issue = Issue.objects.get(scan=scan_obj) 
content_type = ContentType.objects.get_for_model(Issue) 
tickets = Tickets.objects.filter(content_type=content_type, issue=issue) 

還是不行。我需要知道如何在django中完成這些查詢?謝謝。

回答

57

您定義的Ticket.issue字段將幫助您從Ticket實例轉到它附加的Issue,但它不會讓您倒退。您接近第二個示例,但您需要使用issue_id字段 - 無法在GenericForeignKey上進行查詢(只有在您有Ticket實例時才能幫助您檢索對象)。通過創建共享db_tableTicket第二模型跨越GenericForeignKey可以

from django.contrib.contenttypes.models import ContentType 

issue = Issue.objects.get(scan=scan_obj) 
tickets = Ticket.objects.filter(issue_id=issue.id, issue_ct=ContentType.objects.get_for_model(issue)) 
+3

保存我的一天,我的朋友,我試圖弄清楚這一點基本上沒有毛。謝謝 :) 。 – 2012-08-14 20:55:56

+0

@girasquid issue_id非常混亂,因爲它可以引用問題字段issue_id或問題中問題字段的id屬性,我們可以使它們區分嗎? – rohanagarwal 2017-04-07 07:56:15

14

過濾:試試這個。首先將Ticket分成抽象模型和具體模型。

class TicketBase(models.Model): 
    issue_ct = models.ForeignKey(ContentType, related_name='issue_content_type') 
    issue_id = models.PositiveIntegerField(null=True, blank=True) 

    class Meta: 
     abstract = True 

class Ticket(models.Model): 
    issue = generic.GenericForeignKey('issue_ct', 'issue_id') 

然後創建一個模型,該模型也是TicketBase的子類。這個小類將具有除issue之外的所有相同的字段,其被定義爲ForeignKey。添加自定義Manager可以將其過濾爲只有一個ContentType

由於此子類不需要同步或遷移,因此可以使用type()動態創建。

def subclass_for_content_type(content_type): 
    class Meta: 
     db_table = Ticket._meta.db_table 

    class Manager(models.Manager): 
     """ constrain queries to a single content type """ 
     def get_query_set(self): 
      return super(Manager, self).get_query_set().filter(issue_ct=content_type) 

    attrs = { 
     'related_to': models.ForeignKey(content_type.model_class()), 
     '__module__': 'myapp.models', 
     'Meta': Meta, 
     'objects': Manager() 
    } 
    return type("Ticket_%s" % content_type.name, (TicketBase,), attrs) 
+0

這是非常非常聰明的.. – 2016-08-29 22:22:26

相關問題