From b381f46b23c7a2b053ff7bb9b752de47c32acf17 Mon Sep 17 00:00:00 2001 From: "Pavel Turinsky (DebianVM @ Zr)" Date: Tue, 22 Jun 2021 20:41:01 +0000 Subject: [PATCH] Spojovani reseni pro Clanky, aby mely jen jedno... --- db_compare.py | 52 ++++++++++++------- .../0058_problem_to_uloha_tema_clanek.py | 40 ++++++++++++++ 2 files changed, 73 insertions(+), 19 deletions(-) diff --git a/db_compare.py b/db_compare.py index d4e1a777..819805e1 100755 --- a/db_compare.py +++ b/db_compare.py @@ -101,42 +101,56 @@ def check_resitel(): check_same(o,n,fields) def check_reseni(): - old_query = 'SELECT * FROM seminar_reseni ORDER BY id' - new_query = '''SELECT seminar_reseni.id, forma, poznamka, cas_doruceni, hodnoceni.problem_id AS h_problem_id, hodnoceni.body AS h_body, hodnoceni.cislo_body_id AS h_cislo_body_id + # Migrace 0058 zamerne meni (zmensuje) pocet reseni, aby kazdy clanek mel + # jen jedno reseni (s vice resiteli, coz postaru neslo) + # Kvuli tomu je potreba kontrolovat dve veci: + # 1) Ze kazdy resitel dostal za kazdy problem spravne bodu + # 2) Ze detaily reseni zustaly zachovany + + # Cast 1) + old_query = 'SELECT * FROM seminar_reseni ORDER BY problem_id, resitel_id, body, timestamp' + new_query = '''SELECT seminar_reseni.id, forma, seminar_reseni.poznamka, cas_doruceni, hodnoceni.problem_id AS problem_id, hodnoceni.body AS body, hodnoceni.cislo_body_id AS cislo_body_id, res.id AS resitel_id FROM seminar_reseni JOIN seminar_hodnoceni AS hodnoceni ON seminar_reseni.id = hodnoceni.reseni_id - ORDER BY id''' + JOIN seminar_reseni_resitele AS rr ON seminar_reseni.id = rr.reseni_id + JOIN seminar_resitele AS res ON res.id = rr.resitele_id + ORDER BY problem_id, resitel_id, body, cas_doruceni''' - same_fields = ['id', 'forma', 'poznamka'] - renamed_fields = [('timestamp', 'cas_doruceni'), - ('problem_id', 'h_problem_id'), - ('body', 'h_body'), - ('cislo_body_id', 'h_cislo_body_id'), + # Po spojeni nekterych problemu se lisi casy doruceni a poznamky, proto je nebudeme kontrolovat (jde v podstate o triviality, tak je to snad jedno) + same_fields = ['forma', 'problem_id', 'body', 'cislo_body_id', 'resitel_id'] + renamed_fields = [ + #('timestamp', 'cas_doruceni'), ] old_fields = same_fields + [f[0] for f in renamed_fields] new_fields = same_fields + [f[1] for f in renamed_fields] - old_res, new_res = execute_simple(old_query,new_query) + old_res, new_res = execute_simple(old_query, new_query) res = zip(old_res,new_res) for o,n in res: check_same(o,n,old_fields, new_fields) - # Řešitelé jsou nově m2m, takže je musíme dohledat - old_query = 'SELECT id, resitel_id FROM seminar_reseni ORDER BY id' - new_query = 'SELECT reseni_id, resitele_id FROM seminar_reseni_resitele ORDER BY reseni_id' + # Cast 2) + # Query se lisi tim, ze uz nejoinujeme resitele. + old_query = 'SELECT * FROM seminar_reseni ORDER BY id' + new_query = '''SELECT seminar_reseni.id, forma, poznamka, cas_doruceni AS timestamp, h.problem_id AS problem_id, h.body AS body, h.cislo_body_id AS cislo_body_id + FROM seminar_reseni + JOIN seminar_hodnoceni AS h ON h.reseni_id = seminar_reseni.id + ORDER BY id''' - #oldcur = oldconn.cursor() + # execute_simple kontroluje stejnost poctu radku, to nechceme. oldcur.execute(old_query) - old_results = oldcur.fetchall() - #newcur = newconn.cursor() newcur.execute(new_query) - new_results = newcur.fetchall() + old_res, new_res = oldcur.fetchall(), newcur.fetchall() + # Zkontrolujeme, ze pro kazde nove reseni ma stare reseni spravna data. + new_ids = [n['id'] for n in new_res] + spravna_old = list(filter(lambda o: o['id'] in new_ids, old_res)) + res = zip(spravna_old,new_res) + for o,n in res: + check_same(o,n,['id', 'forma', 'poznamka', 'timestamp', 'problem_id', 'body', 'cislo_body_id']) + - for oldr in old_results: - if oldr not in new_results: - raise ValueError(f'Reseni pair {oldr} not found in new db.') def check_organizator(): old_query = 'SELECT * FROM seminar_organizator ORDER BY id' diff --git a/seminar/migrations/0058_problem_to_uloha_tema_clanek.py b/seminar/migrations/0058_problem_to_uloha_tema_clanek.py index 3c947b24..4b09aea9 100644 --- a/seminar/migrations/0058_problem_to_uloha_tema_clanek.py +++ b/seminar/migrations/0058_problem_to_uloha_tema_clanek.py @@ -110,6 +110,45 @@ def clanek_to_Clanek(apps,schema_editor): poskladej_strom(apps, clnode, cl.text_zadani, cl.text_reseni) clnode.save() +def fix_Clanek_Reseni(apps, schema_editor): + Problem = apps.get_model('seminar', 'Problem') + Clanek = apps.get_model('seminar', 'Clanek') + Reseni = apps.get_model('seminar', 'Reseni') + Hodnoceni = apps.get_model('seminar', 'Hodnoceni') + Resitel = apps.get_model('seminar', 'Resitel') + + # Je potreba zajistit, ze clanky budou mit jen jedno reseni -- z pohledu + # modelu nic jineho nedava smysl. Ve stavajicim modelu ale naopak nelze + # reprezentovat vice resitelu jednoho clanku (coz je ale bezne -- clanky z + # konfer) Musime tedy opravit, aby misto nekolika reseni kazdeho resitele + # samostatne zustalo jen jedno reseni, spravne obodovane a s vice resiteli + # jako autory + + for cl in Clanek.objects.all(): + rr = cl.reseni_set.all() + if len(rr) == 1: continue + # Vice nez jedno reseni, jdeme je sjednotit. + resitele = [] + vzor_hodnoceni = rr[0].hodnoceni_set.first() + ostatni_hodnoceni = [] + for r in rr: + # Overime, ze nemame kolizi v datech: + h = r.hodnoceni_set.first() + if h.cislo_body != vzor_hodnoceni.cislo_body or h.body != vzor_hodnoceni.body: + raise ValueError(f'Clanek {cl.id} ma vice nekonzistentnich reseni') + if h.id != vzor_hodnoceni.id: + ostatni_hodnoceni.append(h) + resitele.extend(r.resitele.all()) + print(f'*** cl={cl.id}, res={resitele}') + rr[0].resitele.set(resitele) + rr[0].save() + vzor_hodnoceni.save() + print(f'vzor = {vzor_hodnoceni}, ostatni = {ostatni_hodnoceni}') + # Ted mame spravne databazi, jeste potrebujeme z databaze smazat po novu nepouzita hodnoceni + for h in ostatni_hodnoceni: + h.reseni.delete() + h.delete() + def tema_to_Tema(apps, schema_editor): Problem = apps.get_model('seminar', 'Problem') Tema = apps.get_model('seminar', 'Tema') @@ -155,5 +194,6 @@ class Migration(migrations.Migration): migrations.RunPython(uloha_to_Uloha, migrations.RunPython.noop), migrations.RunPython(tema_to_Tema, migrations.RunPython.noop), migrations.RunPython(clanek_to_Clanek, migrations.RunPython.noop), + migrations.RunPython(fix_Clanek_Reseni, migrations.RunPython.noop), migrations.RunPython(konfery_rucne, migrations.RunPython.noop), ]