diff --git a/program2021/fixtures/characteristic.json b/program2021/fixtures/characteristic.json index 8e8f90390de49d4dc84d1cdd02d9ccfd3e4f5aa8..34070730e94c130eff44d8a993e0827b8766a93c 100644 --- a/program2021/fixtures/characteristic.json +++ b/program2021/fixtures/characteristic.json @@ -3,21 +3,224 @@ "model": "program2021.SearchCharacteristic", "pk": 1, "fields": { - "name": "Pohlaví - žena" + "name": "Žena", + "form_param": "female" } }, { "model": "program2021.SearchCharacteristic", "pk": 2, "fields": { - "name": "Pohlaví - muž" + "name": "Muž", + "form_param": "male" } }, { "model": "program2021.SearchCharacteristic", "pk": 3, "fields": { - "name": "Pohlaví - nezadáno" + "name": "věk do 30", + "form_param": "age30" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 4, + "fields": { + "name": "věk 30-49", + "form_param": "age50" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 5, + "fields": { + "name": "věk 50-64", + "form_param": "age65" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 6, + "fields": { + "name": "věk 65+", + "form_param": "age99" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 7, + "fields": { + "name": "mám děti", + "form_param": "kids" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 8, + "fields": { + "name": "bezdětný/á", + "form_param": "nokids" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 9, + "fields": { + "name": "Student", + "form_param": "student" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 10, + "fields": { + "name": "zaměstnanec*kyně ve veřejné sféře", + "form_param": "employee-public" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 11, + "fields": { + "name": "zaměstnanec*kyně v soukromé sféře", + "form_param": "employee-private" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 12, + "fields": { + "name": "podnikatel*ka", + "form_param": "entrepreneur" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 13, + "fields": { + "name": "na mateřské / rodičovské", + "form_param": "maternity" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 14, + "fields": { + "name": "v důchodu", + "form_param": "retired" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 15, + "fields": { + "name": "Životní údeoveň velmi dobrá", + "form_param": "wealth-great" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 16, + "fields": { + "name": "Životní úroveň dobrá", + "form_param": "wealth-good" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 17, + "fields": { + "name": "Životní úroveň průmerná", + "form_param": "wealth-average" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 18, + "fields": { + "name": "Životní úroveň špatná", + "form_param": "wealth-bad" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 19, + "fields": { + "name": "Cestuji na kole", + "form_param": "travel-bike" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 20, + "fields": { + "name": "Cestuji autem", + "form_param": "travel-car" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 21, + "fields": { + "name": "Cestuji veřejnou dopravou", + "form_param": "travel-public" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 22, + "fields": { + "name": "Žiji ve velkém městě", + "form_param": "metropolis" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 23, + "fields": { + "name": "Žiji ve středním městě", + "form_param": "town" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 24, + "fields": { + "name": "Žiji v malém městě / na vesnici", + "form_param": "village" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 25, + "fields": { + "name": "Základní škola", + "form_param": "zs" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 26, + "fields": { + "name": "Střední škola bez maturity", + "form_param": "ss" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 27, + "fields": { + "name": "SŠ s maturitou", + "form_param": "maturita" + } + }, + { + "model": "program2021.SearchCharacteristic", + "pk": 28, + "fields": { + "name": "Vysoká škola", + "form_param": "vs" } } ] diff --git a/program2021/migrations/0007_auto_20200812_1951.py b/program2021/migrations/0007_auto_20200812_1951.py new file mode 100644 index 0000000000000000000000000000000000000000..959a81069af16a92b394d7276ba0425f22187e87 --- /dev/null +++ b/program2021/migrations/0007_auto_20200812_1951.py @@ -0,0 +1,52 @@ +# Generated by Django 3.0.8 on 2020-08-12 17:51 + +import django.db.models.deletion +import modelcluster.contrib.taggit +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("taggit", "0003_taggeditem_add_unique_index"), + ("program2021", "0006_auto_20200812_1556"), + ] + + operations = [ + migrations.AddField( + model_name="searchcharacteristic", + name="form_param", + field=models.CharField( + blank=True, + max_length=20, + null=True, + verbose_name="ID parametru ve formuláři", + ), + ), + migrations.AlterField( + model_name="characteristicweight", + name="search_characteristic", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="program2021.SearchCharacteristic", + verbose_name="Zadáno", + ), + ), + migrations.AlterField( + model_name="program2021pointpage", + name="search_tags", + field=modelcluster.contrib.taggit.ClusterTaggableManager( + blank=True, + help_text='Deleny do skupin se spolecnym prefixem, napr. "gender". Pokud je bod spolecny pro vsechny moznosti dane skupiny, pouzij tag se suffixem "-every".\nPriklad: chces-li programovy bod pouze pro muze, zadej tag "gender-male", pokud je to jedno, musis zadat tag "gender-every".\nPro kazdou skupinu musis zadat aspon jeden tag, jinak se bod nedostane nikdy do vysledku vyhledavani. Seznam tagu po skupinach:\n(gender-male gender-female gender-every)\n(age-30 age-50 age-65 age-99 age-every)\n(kids-yes kids-no kids-every)\n(occupation-student occupation-employee-public occupation-employee-private occupation-entrepreneur occupation-maternity occupation-retired occupation-every)\n(wealth-excelent wealth-good wealth-average wealth-bad wealth-every)\n(travel-bike travel-car travel-public travel-every)\n(housing-metropolis housing-town housing-village housing-every)\n(education-zs education-ss education-maturita education-vs education-every)\n ', + related_name="search_tags", + through="program2021.Program2021PointPageSearchTag", + to="taggit.Tag", + verbose_name="Tagy pro vyhledávání", + ), + ), + migrations.AlterField( + model_name="searchcharacteristic", + name="name", + field=models.CharField(max_length=200, verbose_name="Název"), + ), + ] diff --git a/program2021/models.py b/program2021/models.py index 4c8abad76e42657932dddd10ca056ce1452e6f6f..34a755a49467ecd48d386e91a745ff3e997352fb 100644 --- a/program2021/models.py +++ b/program2021/models.py @@ -25,6 +25,11 @@ class SearchCharacteristic(models.Model): name = models.CharField("Název", max_length=200, blank=False, null=False) + # mapování chareakteristiky na přislusnou POST promennou odeslanou HTML formularem + form_param = models.CharField( + "ID parametru ve formuláři", max_length=20, blank=True, null=True + ) + def __str__(self): return self.name @@ -83,47 +88,24 @@ class Program2021HomePage(Page): def get_context(self, request): context = super().get_context(request) + if request.method == "POST": - # odeslany formular vyhledavani v programovych bodech. - # Shromazdi vsechny tagy; neni-li nejaky ze skupiny zadan, dodej tag "<skupina>-every" - # Logika: v programovem bodu pak zadas bud tag nepr "gender-male" pro muzska temata - # nebo "gender-every" pro genderove nespecificka. - required_tags = [] - - # tohle jsou checkboxy, muze jich byt zaskrknuto zadny nebo nekolik - for x in ["travel-bike", "travel-car", "travel-public"]: - if request.POST.get(x, ""): - required_tags.append(x) - if not required_tags: - required_tags.append("travel-every") - - # selecty mohou mit vzdy jen jednu hodnotu - for x in [ - "age", - "gender", - "kids", - "occupation", - "wealth", - "housing", - "education", - ]: - required_tags.append(x + "-" + (request.POST.get(x, "") or "every")) - - # TODO : rozpracovana vec, funguje spatne, vrati vsechny body co maji aspon jeden tag - # bude treba prevest na vahy tagu - context["points"] = ( - self.get_children() - .live() - .specific() - .filter(program2021pointpage__search_tags__name__in=required_tags) - .distinct() - ) - raise NotImplementedError + sent_tags = [request.POST.get(x, None) for x in request.POST.keys()] + sent_tags = [x for x in sent_tags if x] + + # dopocitej vahu podle predanych parametru z vyhledavani... + context["points"] = self.get_children().live().specific() + for point in context["points"]: + point.weight = point.get_weight(sent_tags) + + # ...a setrid dle ni vysledky. HACK: pomale, ale pocitame max. v desitkach zaznamu, tedy acceptable + context["points"] = sorted(context["points"], key=lambda x: -x.weight) else: # neformular - vrat vsechny body context["points"] = self.get_children().live().specific() + return context @@ -366,3 +348,14 @@ Pro kazdou skupinu musis zadat aspon jeden tag, jinak se bod nedostane nikdy do class Meta: verbose_name = "Programový bod" + + def get_weight(self, param_ids): + """ Vraci celkovou vahu tagu, predanych v seznamu param_ids """ + # Kvuli prehlednosti nepisu jako oneliner :) + my_weights = self.program_point_link.all() + involved_weights = [ + x.weight + for x in my_weights + if x.search_characteristic.form_param in param_ids + ] + return sum(involved_weights) diff --git a/program2021/templates/program2021/program2021_home_page.html b/program2021/templates/program2021/program2021_home_page.html index 75863280d38506a3afa786a66af70693a6e92a45..29cdb184ec906fad169f157c2595c15979ac284f 100644 --- a/program2021/templates/program2021/program2021_home_page.html +++ b/program2021/templates/program2021/program2021_home_page.html @@ -29,16 +29,16 @@ <div class="col-2 text-right">věk:</div> <div class="col-6 btn-group btn-group-toggle" data-toggle="buttons"> <label class="btn btn-outline-secondary active"> - <input type="radio" name="age" id="age1" value="30" autocomplete="off"> do 30 let + <input type="radio" name="age" id="age1" value="age30" autocomplete="off"> do 30 let </label> <label class="btn btn-outline-secondary"> - <input type="radio" name="age" id="age2" value="50" autocomplete="off"> 30 - 49 let + <input type="radio" name="age" id="age2" value="age50" autocomplete="off"> 30 - 49 let </label> <label class="btn btn-outline-secondary"> - <input type="radio" name="age" id="age3" value="65" autocomplete="off"> 50 - 64 let + <input type="radio" name="age" id="age3" value="age65" autocomplete="off"> 50 - 64 let </label> <label class="btn btn-outline-secondary"> - <input type="radio" name="age" id="age4" value="99" autocomplete="off"> 65+ let + <input type="radio" name="age" id="age4" value="age99" autocomplete="off"> 65+ let </label> <label class="btn btn-outline-secondary"> <input type="radio" name="age" id="age5" value="" autocomplete="off" checked> nechci uvést @@ -50,10 +50,10 @@ <div class="col-2 text-right">mám děti:</div> <div class="col-3 btn-group btn-group-toggle" data-toggle="buttons"> <label class="btn btn-outline-secondary"> - <input type="radio" name="kids" id="kids1" value="yes" autocomplete="off"> ano + <input type="radio" name="kids" id="kids1" value="kids" autocomplete="off"> ano </label> <label class="btn btn-outline-secondary"> - <input type="radio" name="kids" id="kids2" value="no" autocomplete="off"> ne + <input type="radio" name="kids" id="kids2" value="nokids" autocomplete="off"> ne </label> <label class="btn btn-outline-secondary active"> <input type="radio" name="kids" id="kids3" value="" autocomplete="off" checked> nechci uvést @@ -85,10 +85,10 @@ <div class="col-4"> <select class="form-control" id="wealth" name="wealth"> <option value="">jiné / nechci uvést</option> - <option value="excelent">velmi dobrá</option> - <option value="good">dobrá</option> - <option value="average">ani dobrá, ani špatná</option> - <option value="bad">špatná</option> + <option value="wealth-great">velmi dobrá</option> + <option value="wealth-good">dobrá</option> + <option value="wealth-average">ani dobrá, ani špatná</option> + <option value="wealth-bad">špatná</option> </select> </div> </div> @@ -99,15 +99,15 @@ </div> <div class="col-4"> <div class="custom-control custom-checkbox"> - <input type="checkbox" class="custom-control-input" id="travel1" name="travel-bike"> + <input type="checkbox" class="custom-control-input" id="travel1" value="travel-bike" name="travel-bike"> <label class="custom-control-label" for="travel1">na kole</label> </div> <div class="custom-control custom-checkbox"> - <input type="checkbox" class="custom-control-input" id="travel2" name="travel-car"> + <input type="checkbox" class="custom-control-input" id="travel2" value="travel-car" name="travel-car"> <label class="custom-control-label" for="travel2">autem</label> </div> <div class="custom-control custom-checkbox"> - <input type="checkbox" class="custom-control-input" id="travel3" name="travel-public"> + <input type="checkbox" class="custom-control-input" id="travel3" value="travel-public" name="travel-public"> <label class="custom-control-label" for="travel3">veřejnou dopravou</label> </div> </div>