Django按通用外键排序 [英] Django Order By Generic Foreign Key

查看:156
本文介绍了Django按通用外键排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个很快的。我有两个模型,邮政和期限,我想能够标记和分类(分类)职位以及其他(未来)模型。我的帖子模型有以下字段:标题,内容,已发布(日期),我的条款声明如下:

  (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

解决方案

关于带有连接的简单SQL查询是正确的。几个连接实际上。这是对我有用的(django> = 1.2 for 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% )s ON%(posts)s.id =%(relations)s.object_id JOIN%(术语)s ON%(关系)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,
'relation':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%(relationships)s ON%(objects)s.id = %(关系)s.object_id AND%(relationship)s.content_type_id =%(content_type)s JOIN%(terms)s ON%(relationships)s.term_id =%(terms)s.id WHERE%(terms) id =%(term_id)s%(order_by)s'%data)


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. 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:

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. 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. I know there must be a way to solve it. Any ideas?

Thanks ~ K

解决方案

Yeah, I was quite right about the simple SQL query with a join. A few joins actually. Here's what worked for me (django >= 1.2 for the raw() method)

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?

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

这篇关于Django按通用外键排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆