2012-08-14 1 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) 

여전히 작동하지 않습니다. 장고에서 이러한 종류의 쿼리를 수행하는 방법을 알아야합니까? 감사.

답변

57

정의한 Ticket.issue 필드는 Ticket 인스턴스가 연결되어있는 Issue으로 이동하는 데 도움이되지만 뒤로 이동하지는 않습니다. 두 번째 예제와 비슷하지만 issue_id 필드를 사용해야합니다. GenericForeignKey에서 쿼리 할 수 ​​없습니다 (Ticket 인스턴스가있을 때 개체를 검색하는 데 도움이됩니다). 이 시도 :

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

내 날, 내 친구, 나는 이것을 알아 내려고 기본적으로 털이 없습니다. 감사 :) . –

+0

@ girasquid issue_id는 질문의 문제 필드 또는 문제 필드의 id 속성을 참조 할 수 있으므로 매우 혼란 스럽습니다.이를 구분할 수 있습니까? – rohanagarwal

14

필터링을 GenericForeignKey 캔에 걸쳐 Ticketdb_table을 공유하는 두 번째 모델을 만들어. 먼저 티켓을 추상 모델과 구체적인 모델로 나눕니다.

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

이것은 매우 똑똑합니다. –