Browse Source

Spojovani reseni pro Clanky, aby mely jen jedno...

middleware_test
Pavel Turinsky (DebianVM @ Zr) 3 years ago
parent
commit
b381f46b23
  1. 50
      db_compare.py
  2. 40
      seminar/migrations/0058_problem_to_uloha_tema_clanek.py

50
db_compare.py

@ -101,17 +101,25 @@ 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]
@ -123,20 +131,26 @@ def check_reseni():
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'

40
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),
]

Loading…
Cancel
Save