Группировка объектов django с использованием QuerySet API по общим текстовым тегам с использованием двух моделей с отношением ForeignKey

Привет, я пытаюсь написать веб-приложение django, которое находится поверх устаревшей базы данных, поэтому я не могу слишком много контролировать свои поля модели и достигать функциональности, используя новые модели.

У меня есть много документов с пользовательскими тегами, разделенными запятыми. Я хочу сгруппировать «связанные» документы на основе общих тегов.

# Model to express legacy table
class Document(models.Model):
    id = models.BigIntegerField(primary_key= True)
    metadata_id = models.CharField(max_length=384)
    tags_as_csv = models.TextField()

# Created new Model tag_text extracted from tags_as_csv
class Tagdb(models.Model):
    tagid = models.BigIntegerField(primary_key=True)
    referencing_document = models.ForeignKey(Document)
    tag_text = models.TextField(blank=True)

Таким образом, документ будет содержать:

Document : 
id = 1 , 
metadata_id = "a1ee3df3600c6f77a6e851781f7e70c6" , 
tags_as_csv = "raw-data , high temperature , important"

Tagdb будет иметь такие записи, как

id , referencing_document , tag_text
1  , 1 , "raw-data" 
2  , 1 , "high temperature"
3  , 1 , "important"
4  , 2 , "important"
5  , 2 , "processed-data"
6  , 3 , "important"
7  , 4 , "processed-data"

Теперь я хочу извлечь все объекты Document, которые соответствуют тегам, соответствующим родительскому документу. Что я и делаю, используя следующий метод get_queryset.

   def get_queryset(self, **kwargs):
        parent_document = Document.objects.get(id=self.kwargs['slug'])
        tags_in_parent_document = [x.tag_text for x in Tagdb.objects.filter(referencing_document=parent_document.id)]
        # This will contain all the Document ids that match all the tags
        queryset_with_duplicates = []
        for tag in tags_in_parent_document:
            queryset_with_duplicates.extend([x.referencing_document.id for x in Tagdb.objects.filter(tagtext__icontains=tag)])

        # Make sure we have only unique ids
        queryset_unique = set(queryset_with_duplicates)

        # Get all the Document objects 
        queryset = Document.objects.filter(id__in=queryset_unique)

        return queryset

Мой вопрос: есть ли лучший способ. Могу ли я каким-то образом получить все документы, содержащие все теги в родительском документе, и отфильтровать дубликаты (поскольку несколько документов содержат один и тот же тег).


person harijay    schedule 07.03.2012    source источник


Ответы (1)


Вам лучше создать две дополнительные модели: одну для тега и одну для связи между тегом и документом. Если это почему-то неприемлемо, вы можете использовать что-то вроде:

Document.objects.filter(tagdb__tag_text__in=doc.tags_as_csv.split(' , ')).distinct()

Кроме того, добавьте метод модели для получения/установки тегов, это облегчит любой возможный рефакторинг.

person ilvar    schedule 07.03.2012
comment
Я последовал вашему совету и создал модель ManyToManyField, которая связала их вместе. Жизнь проще с вновь созданной таблицей, как вы рекомендовали, например, с автоматически созданными поисками полей, которые являются результатом сопоставления ManyToManyField. Однако я столкнулся с новой проблемой. Интересно, как я могу объединить поиск __in с поиском __icontains. stackoverflow.com/questions/9647142/ - person harijay; 10.03.2012