如何创建两个不同的Django模型的联合?

时间:2018-11-27 08:55:15

标签: mysql django django-models union

我有两个Django模型

package mapmoocer;

import static org.powermock.api.mockito.PowerMockito.when;

import java.util.ArrayList;
import java.util.Map;

import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.modules.testng.PowerMockObjectFactory;
import org.testng.Assert;
import org.testng.IObjectFactory;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.ObjectFactory;
import org.testng.annotations.Test;


public class PersonTest {

    @InjectMocks
    PersonStore personStore = new PersonStore();

    @ObjectFactory
    public IObjectFactory getObjectFactory() {
        return new PowerMockObjectFactory();
    }

    @Mock
    Map<String, java.util.List<Person>> personMap;

    @BeforeClass
    public void before(){
        MockitoAnnotations.initMocks(this);
    }

    @AfterClass
    public void after() {

    }


    @Test
    public void test_hello() {
        personStore.hello();
    }

    @Test(dataProvider="store")
    public void test_check(Object data) {
        java.util.List<Person> persons = (java.util.List<Person>)data;
        when(personMap.get("RAM")).thenReturn(persons);
        personStore.check();
    }

    public Object[][] store() {
        Person person = new Person();
        person.setEmail("aa");
        person.setName("AA");

        java.util.List<Person> value = new ArrayList<Person>();
        value.add(person);

        Object[][] result = {
                {value}
        };
        return result;
    }

}

然后我想使用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`)

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

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分: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`)

答案 2 :(得分:0)

在Django中,联合操作需要具有相同的列,因此,使用<script src="https://unpkg.com/vue@latest/dist/vue.js"></script> <div id="app"> <textarea rows="16" cols="40" v-model.lazy="jsonString"> </textarea> <component :is="componentSpec"></component> </div>只能像下面这样使用这些特定的列:

values_list

但是(我知道)没有办法在Django中模仿qsa = ModelA.objects.all().values('text_a', 'title') qsb = ModelB.objects.all().values('text_a', 'title') qsa.union(qsb) 的并集。因此,有两种方法可以在这里进行操作。

第一个,在模型中添加一个名称为NULL的额外字段。您可以像这样将这些值留空:

other_column

并按照here中所述使用Django queryset联合操作。

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

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

希望有帮助!