简体   繁体   English

Django通过通用外键排序

[英]Django Order By Generic Foreign Key

Hey, this is a quick one. 嘿,这是一个快速的。 I have two models, Post and Term and I'd like to be able to tag and categorize (taxonomy) posts as well as other (future) models. 我有两个模型,即Post和Term,我希望能够对(分类)帖子以及其他(未来)模型进行标记和分类。 My Post model has the following fields: title, content, published (date) and my Term is declared like this: 我的帖子模型具有以下字段:标题,内容,发布(日期),并且我的条款的声明如下:

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

Then I have a TermRelation model that sticks Terms to Posts and other models, like this: 然后,我有了一个TermRelation模型,该模型将术语粘贴到Posts和其他模型上,如下所示:

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

Everything works as expected but my question is the following. 一切正常,但我的问题如下。 I'd like to create an archive of posts in a certain category, and order the posts by their publish date. 我想创建某个类别的帖子存档,并按发布日期排序帖子。 This is what I'm trying to do: 这就是我想要做的:

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

And it works fine, although it's sorted by the relation PK I guess. 尽管按我想的关系PK排序,但它工作正常。 When I try to do the following: 当我尝试执行以下操作时:

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

I get an error saying that there's no content_object field in TermRelation. 我收到一条错误消息,指出TermRelation中没有content_object字段。 I know there must be a way to solve it. 我知道一定有办法解决。 Any ideas? 有任何想法吗?

Thanks ~ K 谢谢〜K

Yeah, I was quite right about the simple SQL query with a join. 是的,对于带有联接的简单SQL查询,我是非常正确的。 A few joins actually. 实际上有一些加入。 Here's what worked for me (django >= 1.2 for the raw() method) 这是对我有用的东西( raw()方法的django> = 1.2)

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)

Wasn't that difficult. 没那么难。 Maybe I should wrap it up in a method to TermRelation, what do you think? 也许我应该将其包装到TermRelation的方法中,您认为呢?

Update: I did wrap it up into a static method and made it more universal to deal with different content types and sort orders. 更新:我确实将它包装成一个静态方法,并使其更通用以处理不同的内容类型和排序顺序。 It does still assume that there's a field called content_type_id which is created by default if there's a foreign key on ContentType. 它仍然假定存在一个名为content_type_id的字段,如果ContentType上有外键,则默认情况下会创建该字段。 Here's the code: 这是代码:

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

As far as i know this is not possible with django, because the order_by -arguments are translated to database columns/tables and content_object doesn't exit in the database like this. 据我所知,使用django是不可能的,因为order_by -arguments会转换为数据库列/表,而content_object不会像这样在数据库中退出。 This is also the reason why you have to do a content type lookup with object_id/content_type... 这也是为什么必须使用object_id / content_type查找内容类型的原因...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM