2012-08-14 5 views
39

Ich bin neu in der Verwendung von GenericForeignKey, und ich konnte es nicht in einer Abfrage-Anweisung arbeiten. Die Tische sind in etwa wie folgt aus:django: Wie frage ich basierend auf Felder von GenericForeignKey ab?

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) 

Ein Scan ein Problem erzeugt, erzeugt ein Problem, einige Karten, und ich machte Ausgabe als Fremdschlüssel zu Ticket-Tabelle. Jetzt habe ich ein Scan-Objekt und möchte alle Tickets abfragen, die mit diesem Scan zusammenhängen. Ich habe das zuerst versucht:

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

was nicht funktioniert. Dann habe ich das versucht:

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) 

Funktioniert immer noch nicht. Ich muss wissen, wie man solche Anfragen im Django macht? Vielen Dank.

Antwort

57

Das Ticket.issue Feld, das Sie definiert haben, werden Sie von einem Ticket Instanz zum Issue gehen helfen, es zu angebracht ist, aber es wird Sie gehen nach hinten nicht lassen. Sie sind nah bei Ihrem zweiten Beispiel, aber Sie müssen das Feld issue_id verwenden - Sie können nicht auf die GenericForeignKey abfragen (es hilft Ihnen nur das Objekt abzurufen, wenn Sie eine Ticket Instanz haben). Versuchen Sie folgendes:

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

Mein Tag gerettet, mein Freund, ich bin im Grunde haarlos nach dem Versuch, dies herauszufinden. Vielen Dank :) . –

+0

@girasquid issue_id ist sehr verwirrend, da es sich auf das Feld issue_id in Frage oder das ID-Attribut des Fragefeldes in der Frage beziehen kann, können wir sie unterscheidbar machen? – rohanagarwal

14

Filtering über eine GenericForeignKey durch ein zweites Modell zu schaffen, das die db_table mit Ticket teilt. Teilen Sie Ticket zunächst in ein abstraktes Modell und ein konkretes Modell auf.

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') 

Dann ein Modell erstellen, die auch TicketBase Unterklassen. Diese Unterklasse hat alle die gleichen Felder außer issue, die stattdessen als ForeignKey definiert ist. Durch Hinzufügen einer benutzerdefinierten Manager kann es auf nur eine einzige ContentType gefiltert werden.

Da diese Unterklasse nicht synchronisiert oder migriert werden muss, kann sie dynamisch mit type() erstellt werden.

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

Das ist sehr, sehr schlau .. –