Орден Джанго по универсальному внешнему ключу - PullRequest
1 голос
/ 19 октября 2010

Эй, это быстро. У меня есть две модели, Post и Term, и я хотел бы иметь возможность отмечать и классифицировать (таксономические) сообщения, а также другие (будущие) модели. Модель My Post имеет следующие поля: заголовок, контент, опубликовано (дата), а мой термин объявлен так:

class Term(models.Model):
    taxonomy = models.CharField(max_length=255)
    name = models.CharField(max_length=255)
    slug = models.SlugField(max_length=50)

Тогда у меня есть модель TermRelation, которая привязывает условия к сообщениям и другим моделям, например:

class TermRelation(models.Model):
    term = models.ForeignKey(Term)
    object_id = models.PositiveIntegerField()
    content_type = models.ForeignKey(ContentType)
    content_object = generic.GenericForeignKey()

Все работает как положено, но мой вопрос заключается в следующем. Я хотел бы создать архив сообщений в определенной категории и упорядочить сообщения по дате их публикации. Вот что я пытаюсь сделать:

ctype = ContentType.objects.get_for_model(Post)
relations = TermRelation.objects.filter(content_type__pk=ctype.id)

И он работает нормально, хотя, я думаю, он отсортирован по соотношению PK. Когда я пытаюсь сделать следующее:

relations = TermRelation.objects.filter(content_type__pk=ctype.id).order_by('content_object__published')

Я получаю сообщение о том, что в TermRelation отсутствует поле content_object. Я знаю, что должен быть способ решить это. Есть идеи?

Спасибо ~ K

Ответы [ 2 ]

2 голосов
/ 19 октября 2010

Да, я был совершенно прав насчет простого SQL-запроса с объединением. Несколько присоединений на самом деле. Вот что сработало для меня (django> = 1.2 для метода raw())

data = {
    'posts': Post._meta.db_table,
    'relations': TermRelation._meta.db_table,
    'terms': Term._meta.db_table,
    'tag_id': tag.id
}

posts = Post.objects.raw('SELECT %(posts)s.* FROM %(posts)s JOIN %(relations)s ON %(posts)s.id = %(relations)s.object_id JOIN %(terms)s ON %(relations)s.term_id = %(terms)s.id WHERE %(terms)s.id = %(tag_id)s ORDER BY %(posts)s.published DESC' % data)

Это было не так сложно. Может быть, я должен обернуть это в метод TermRelation, как вы думаете?

Обновление: Я обернул его в статический метод и сделал его более универсальным для работы с различными типами контента и порядками сортировки. Он все еще предполагает, что есть поле с именем content_type_id, которое создается по умолчанию, если есть внешний ключ в ContentType. Вот код:

@staticmethod
def get_objects_by_term_id(model=None, taxonomy=None, term_id=None, order_by='NULL'):
    data = {
        'objects': model._meta.db_table,
        'content_type': ContentType.objects.get_for_model(model).id,
        'relations': TermRelation._meta.db_table,
        'terms': Term._meta.db_table,
        'term_id': term_id,
        'order_by': ' ORDER BY %s ' % order_by
    }

    return model.objects.raw('SELECT %(objects)s.* FROM %(objects)s JOIN %(relations)s ON %(objects)s.id = %(relations)s.object_id AND %(relations)s.content_type_id = %(content_type)s JOIN %(terms)s ON %(relations)s.term_id = %(terms)s.id WHERE %(terms)s.id = %(term_id)s %(order_by)s' % data)
1 голос
/ 19 октября 2010

Насколько я знаю, это невозможно с django, потому что order_by -аргументы транслируются в столбцы / таблицы базы данных, а content_object не завершается в базе данных, как это. Это также причина, почему вы должны выполнить поиск типа контента с object_id / content_type ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...