django: ¿cómo hago una consulta basada en los campos de GenericForeignKey?
generic-foreign-key (2)
El campo Ticket.issue
que ha definido lo ayudará a pasar de una instancia de Ticket
al Issue
que está adjunto, pero no le permitirá retroceder. Está cerca del segundo ejemplo, pero necesita usar el campo issue_id
: no puede consultar en GenericForeignKey
(solo le ayuda a recuperar el objeto cuando tiene una instancia de Ticket
). Prueba esto:
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))
Soy nuevo en el uso de GenericForeignKey y no pude hacerlo funcionar en una declaración de consulta. Las tablas son aproximadamente como las siguientes:
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)
Un escaneo crea un problema, un problema genera algunos tickets y yo hice el Issue como una clave externa para la tabla de tickets. Ahora tengo un objeto de escaneo y deseo consultar todos los tickets relacionados con este escaneo. Intenté esto primero
tickets = Tickets.objects.filter(issue__scan=scan_obj)
que no funciona Entonces intenté esto:
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)
Todavía no funciona. ¿Necesito saber cómo hacer este tipo de consultas en django? Gracias.
El filtrado a través de un GenericForeignKey
puede crear un segundo modelo que comparte la db_table
con Ticket
. Primer boleto dividido en un modelo abstracto y un modelo concreto.
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'')
Luego crea un modelo que también subclasifique TicketBase
. Esta subclase tendrá todos los mismos campos, excepto el issue
que, en cambio, se define como ForeignKey
. Agregar un Manager
personalizado permite filtrarlo a un solo ContentType
.
Como esta subclase no necesita ser sincronizada o migrada, puede crearse dinámicamente usando 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)