简体   繁体   中英

How to compare two Django models and display the answer in the third model

I have two completely identical models in structure:

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

First, I try to compare all the field values with each other.

Second, if the parameters are not the same, and write the answer in the third table(indicating each inequality by its ID and field name).

 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)

How do I perform this action using Python models? Provided that the models have a lot of fields and the models themselves are more than 40 pieces.

Here is an example of what I want to do with the sql query example.

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

Here is what I ideally want to get:

I would like to group inconsistencies by their ID and fields name.

I have 1 table and 2 table with identical ID's.

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           |
+---+------------+------------------+--------------+------------------------+-------------------------+----------------------+

Consider something along the lines of:

# 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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM