2015-09-17 3 views
1

У меня есть модель под названием «Комментарии», который использует общий внешний ключ:Django общий внешний ключ обратного фильтра

class CommentManager(models.Manager): 

    def for_model(self, model): 
     """ 
     QuerySet for all comments for a particular model (either an instance or 
     a class). 
     """ 
     ct = ContentType.objects.get_for_model(model) 
     qs = self.get_query_set().filter(content_type=ct) 
     if isinstance(model, models.Model): 
      qs = qs.filter(object_pk=force_text(model._get_pk_val())) 
     return qs 


class Comment(models.Model): 
    """ 
    A user comment about some object. 
    """ 
    status = models.CharField(max_length=12, blank=True, null=True) 
    sub_status = models.CharField(max_length=500, blank=True, null=True) 
    comment = models.TextField() 

    content_type = models.ForeignKey(
     ContentType, 
     verbose_name=_('content type'), 
     related_name="content_type_set_for_%(class)s") 
    object_pk = models.TextField(_('object ID')) 
    content_object = generic.GenericForeignKey(ct_field="content_type", 
               fk_field="object_pk") 

Одна из вещей, которые вы можете поместить комментарии на это Tickets:

class Ticket(CommonModel): 
    type = models.ForeignKey(TicketType) 
    priority = models.PositiveSmallIntegerField() 
    status = models.ForeignKey(TicketStatus) 
    access_serial_number = models.PositiveSmallIntegerField(null=True) 
    parent = models.ForeignKey('self', null=True, related_name='child') 
    submitted = models.DateTimeField() 

Я делаю много фильтрации Tickets - в прошлом все, что я делал с комментариями к Билетам, это то, что когда я показывал Ticket, я использовал Comments.objects.for_model(ticket), чтобы найти все комментарии для него. Но теперь я хочу найти Tickets, которые имеют конкретный текст в комментарии. Нет comment_set или эквивалент с GenericForeignKey.

Это то, что я придумал, но это довольно ужасно:

comment_ticket_ids = [int(c.object_pk) for c in Comment.objects.for_model(Ticket).filter(comment__icontains='error')] 
tickets = Ticket.filter(status=open_status, id__in=comment_ticket_ids) 

Там должно быть лучше.

+0

Как вы относите 'Комментарии' к' Билетам'? Я прочитал ваш вопрос несколько раз, но я не вижу отношения в вашем примере кода. – djq

+1

Я добавляю комментарии к билетам с помощью content_object 'GenericForeignKey', как в' comment = Comment (content_object = my_ticket, status = "Ticket Created", comment = "Так и так создал этот билет для усмешек"). Save() ' –

ответ

0

Возможно, вы можете добавить что-то, используя .extra(), чтобы помочь. Вместо

comment_ticket_ids = [int(c.object_pk) for c in Comment.objects.for_model(Ticket).filter(comment__icontains='error')] 
tickets = Ticket.filter(status=open_status, id__in=comment_ticket_ids) 

Вы можете прикрепить поле id_wanted:

extra_select = { 
'id_wanted': 'CASE WHEN (SELECT COUNT(*) FROM tickets WHERE comments something) > 0 THEN TRUE ELSE FALSE END' 
} 

Затем фильтр для билетов с дополнительной выбрать:

tickets = Tickets.objects.filter(ticket__status=open_status, id_wanted__isnull=False).extra(extra_select) 

Это не совсем ясно, почему ты не может иметь отношения FKey между этими двумя моделями.

+0

1. Мы используем GenericForeignKey, потому что вы можете прикреплять комментарии к вещам, отличным от билетов. –

+0

2. Я не понимаю, как работает ваше предложение - похоже, он добавляет «id_wanted» в комментарий, а затем ожидает, что он будет там в запросе, который не связан с комментарием? –

+0

Я пересмотрел свой ответ - удалю, если не полезно. Я пытаюсь перевести шаблон, который использовал, где у меня также было отношение типа содержимого (дающее комментарии ко многим различным объектам) и использовавшее предложение '.extra()' в нашем запросе – djq

Смежные вопросы