如何创建两个不同 django 模型的并集?

问题描述 投票:0回答:4

我有两个 django 模型

class ModelA(models.Model):
    title = models.CharField(..., db_column='title')
    text_a = models.CharField(..., db_column='text_a')
    other_column = models.CharField(/*...*/ db_column='other_column_a')


class ModelB(models.Model):
    title = models.CharField(..., db_column='title')
    text_a = models.CharField(..., db_column='text_b')
    other_column = None 

然后我想使用

union

合并该模型的两个查询集
ModelA.objects.all().union(ModelB.objects.all())

但是在查询中我看到了

(SELECT
`model_a`.`title`,
`model_a`.`text_a`,
`model_a`.`other_column`
FROM `model_a`)

UNION
(SELECT
`model_b`.`title`,
`model_b`.`text_b`
FROM `model_b`)

当然我有例外

The used SELECT statements have a different number of columns

如何创建别名和假列以使用联合查询?

mysql django django-models union
4个回答
7
投票

您可以注释最后一列以弥补列号不匹配。

a = ModelA.objects.values_list('text_a', 'title', 'other_column')
b = ModelB.objects.values_list('text_a', 'title')
        .annotate(other_column=Value("Placeholder", CharField()))

# for a list of tuples
a.union(b)

# or if you want list of dict
# (this has to be the values of the base query, in this case a)

a.union(b).values('text_a', 'title', 'other_column')


0
投票

在SQL查询中,我们可以使用

NULL
来定义剩余的列/别名

(SELECT
`model_a`.`title`,
`model_a`.`text_a`,
`model_a`.`other_column`
 FROM `model_a`)

UNION

(SELECT
`model_b`.`title`,
`model_b`.`text_b`, 
 NULL
 FROM `model_b`)

0
投票

在 Django 中,联合操作需要具有相同的列,因此使用

values_list
,您只能像这样使用这些特定列:

qsa = ModelA.objects.all().values('text_a', 'title')
qsb = ModelB.objects.all().values('text_a', 'title')

qsa.union(qsb)

但是(据我所知)没有办法在 Django 中模仿 union 中的

NULL
。因此,您可以通过两种方式继续。

第一个,在模型中添加一个名为

other_column
的额外字段。您可以将值设置为空,如下所示:

other_column = models.CharField(max_length=255, null=True, default=None)

并使用 Django 查询集联合操作,如此处中所述。

最后一个,这种方法有点Pythonic。尝试这样:

a = ModelA.objects.values_list('text_a', 'title', 'other_column')
b = ModelB.objects.values_list('text_a', 'title')

union_list = list()

for i in range(0, len(a)):
     if b[i] not in a[i]:
         union_list.append(b[i])
     union_list.append(a[i])

希望有帮助!!


0
投票
ModelA.objects.all() \
.union(
     ModelB.objects
     .annotate(othercolumn=Value("")
     .all())
© www.soinside.com 2019 - 2024. All rights reserved.