首页 > 解决方案 > 如何比较两个 Django 模型并在第三个模型中显示答案

问题描述

我在结构上有两个完全相同的模型:

class Model_A (models.Model)
    id_value     = models.CharField(primary_key=True, max_length=45)
    some_value_1 = models.IntegerField(blank=True, null=True)
    some_value_2 = models.TextField(blank=True, null=True)
    #and etc. I have many fields

class Model_B (models.Model)
    id_value     = models.CharField(primary_key=True, max_length=45)
    some_value_1 = models.IntegerField(blank=True, null=True)
    some_value_2 = models.TextField(blank=True, null=True)
    #and etc. I have many fields

首先,我尝试将所有字段值相互比较。

第二,如果参数不一样,把答案写在第三张表中(用ID和字段名表示每个不等式)。

 class Third_Model(models.Model):
     auto_increment_id    = models.AutoField(primary_key=True)
     id_value             = models.CharField(max_length=45, null=False)
     manage_objects       = models.CharField(blank=True, null=True)
     field_name           = models.CharField(blank=True, null=True)
     value_from_A         = models.CharField(blank=True, null=True)
     value_from_B         = models.CharField(blank=True, null=True)

如何使用 Python 模型执行此操作?前提是模型领域多,模型本身40多件。

这是我想对 sql 查询示例执行的操作的示例。

INSERT INTO `third_table` (`id_value`, `manage_objects`,`field_name`,  `value_from_A`, `value_from_B`)
SELECT id_value, manage_objects, param_name, fld_param , ref_param FROM
(SELECT  id_value,  'Model_name' AS manage_objects,  param_name,  max(val1) AS fld_param, max(val2) AS ref_param 
FROM ((SELECT id_value, 'some_value_1' AS param_name, some_value_1 AS val1, Null AS val2
       FROM model_a
      ) UNION ALL
      (SELECT id_value, 'some_value_2' as param_name, some_value_2 AS val1, Null AS val2
       FROM model_a
      )UNION ALL
      (SELECT id_value, 'some_value_1' as param_name, Null AS val1, some_value_1 AS val2
       FROM model_b
      )  UNION ALL
      (SELECT id_value, 'some_value_2' as param_name, Null AS val1, some_value_2 AS val2
       FROM model_b
      )
       ) tcd
GROUP BY id_value, param_name
HAVING NOT max(val1) <=> max(val2)) as inconsis
WHERE CAST(fld_param AS CHAR) !='Null' AND CAST(ref_param AS CHAR) !='Null';

这是我理想中想要得到的:

我想按其 ID 和字段名称对不一致进行分组。

我有 1 个表和 2 个具有相同 ID 的表。

Table model_a
+------+------------+-------------+---------------+-------------------------+
| #    | id_value   | some_value_1| some_value_2  | some_value_3            |
+------+------------+-------------+---------------+-------------------------+
| 1523 | Wien       | AUT         | Wien          | {"Population": 1608144} |
| 1524 | Graz       | AUT         | Steiermark    | {"Population": 240967}  |
| 1525 | Linz       | AUT         | North Austria | {"Population": 188022}  |  
+------+------------+-------------+---------------+-------------------------+

Table model_b
+------+------------+-------------+---------------+-------------------------+
| #    | id_value   | some_value_1| some_value_2  | some_value_3            |
+------+------------+-------------+---------------+-------------------------+
| 1523 | Wien       | RUS         | Wien          | {"Population": 666666}  |
| 1524 | Graz       | AUT         |               | {"Population": 240967}  |
| 1525 | Linz       | AUT         | North Austria | {"Population": 188022}  |
+------+------------+-------------+---------------+-------------------------+



Table third_model
+---+------------+------------------+--------------+------------------------+-------------------------+----------------------+
| # | id_value   |  manage_objects  |  field_name  | value_from_a           |      value_from_b       |  auto_increment_id   |
+---+------------+------------------+--------------+------------------------+-------------------------+----------------------+
| 1 | Wien       |      model_a     | some_value_1 | AUT                    | RUS                     |          1           |
| 2 | Wien       |      model_a     | some_value_3 |{"Population": 1608144} | {"Population": 666666}  |          2           |
| 3 | Graz       |      model_a     | some_value_2 |                        | Steiermark              |          3           |
+---+------------+------------------+--------------+------------------------+-------------------------+----------------------+

标签: djangopython-3.xdjango-models

解决方案


考虑以下内容:

# Get instances to be compared, for example, if you are going through all instances:
model_a_queryset = Model_A.objects.all()

for instance_a in model_a_queryset:
    instance_b = Model_B.objects.get(id=instance_a.id)
    # Since both Model_A and Model_B have the same fields, 
    # it does not matter which instance you use to get the fields and loop over them
    for field in instance_a.__class__._meta.fields:
        field_name = field.name
        # compare field values for both instances
        if getattr(instance_a, field_name) != getattr(instance_b, field_name):
            # create instance of Model_C if fields are not the same
            instance_c = Model_C(
                id_value=instance_a.id,
                value_from_A=getattr(instance_a, field_name),
                value_from_B=getattr(instance_b, field_name),
            ).save()

推荐阅读