Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 通过两个串联的M2M字段对Django queryset进行排序_Python_Django_Orm_M2m - Fatal编程技术网

Python 通过两个串联的M2M字段对Django queryset进行排序

Python 通过两个串联的M2M字段对Django queryset进行排序,python,django,orm,m2m,Python,Django,Orm,M2m,我有以下Django模型(此处大大简化): 出版物可以有作者也可以有编辑,但不能同时有作者和编辑。我想按作者和编辑的统一顺序订购一份出版物清单,按字母顺序排序。换句话说,我想按虚拟字段排序,我们称之为creators,它是作者和编辑的串联 查询: Publication.objects.all().order_by('authors__name', 'editors__name') 。。。将没有作者的出版物聚集在一起,并在该组中根据编辑进行排序,这不是我想要的。实际上,它应该使用出版物上可用的

我有以下Django模型(此处大大简化):

出版物可以有作者也可以有编辑,但不能同时有作者和编辑。我想按作者和编辑的统一顺序订购一份出版物清单,按字母顺序排序。换句话说,我想按虚拟字段排序,我们称之为
creators
,它是作者和编辑的串联

查询:

Publication.objects.all().order_by('authors__name', 'editors__name')
。。。将没有作者的出版物聚集在一起,并在该组中根据编辑进行排序,这不是我想要的。实际上,它应该使用出版物上可用的任何作者或编辑,并按其排序


这种排序必须在数据库级别进行,结果集可能很大。

一种方法是创建一个名为
创建者的方法:

class Publication:
    authors = models.ManyToManyField(Author)
    editors = models.ManyToManyField(Editor)

    def creators(self):
        return self.authors + self.creators
但缺点是不能在数据库级别执行排序,而只能在Python级别执行排序:

sorted(Publication.objects.all(), key=lambda k: " ".join(p.name for p in k))

我能把这个扔出去吗


您可能希望
作者
编辑器
贡献者
继承。由于这两个模型都有名字和姓氏、地址等内容。

要按定义了值的字段进行排序,您需要在QuerySet可以访问的地方创建一个组合字段,可以在模型级别使用自定义聚合,也可以使用额外的子句

如果您不需要完全不了解数据库,那么extra可能是最容易实现的:

qs = Publication.objects.extra({
   select={'contributor': "COALESCE(author.name,editor.name)"}
})
qs.extra(order_by = ['contributor'])

如果您确实需要独立于数据库,那么应该考虑使用concat的一个实现作为聚合。比如说,


结果集非常庞大,因此必须在DB级别进行排序。我已将此添加为我的问题的注释。:)为什么不在保存时添加一个包含已排序名称列表的附加列?在执行join.M2M字段时,您必须对名称进行排序,还记得吗?M2M关系列表可以在不调用save()的情况下更改。True。但是您仍然可以通过
模型和信号使用
,这是一个非常简化的示例。这种继承不会改变问题,只会在示例中添加不必要的额外行。(也就是说,实际上将两个字段合并为一个字段将是一种解决方案,但在这种情况下,由于其他限制,不适合这样做。)嗯。那么,您可以使用原始sql执行此操作。但这是最后一种手段,不是吗?好吧,使用.extra()和
select
来连接两个连接的M2M值列表是我现在要考虑的。小贴士(谢谢)我希望能够使用类似于您的
extra()
建议的东西,但我无法使它与我的M2M字段一起工作。请记住,每个出版物都可以有多个作者,编辑也是如此。有什么想法吗?
qs = Publication.objects.extra({
   select={'contributor': "COALESCE(author.name,editor.name)"}
})
qs.extra(order_by = ['contributor'])