Jonas Havelka
3 years ago
27 changed files with 1329 additions and 1247 deletions
@ -0,0 +1,4 @@ |
|||||
|
""" |
||||
|
Obsahuje vše okolo registrace a osobních údajů (ne přihlášení a změnu hesla). |
||||
|
Také obsahuje rozcestníky a Řešitele s Organizátorem. |
||||
|
""" |
@ -0,0 +1,48 @@ |
|||||
|
from django.contrib import admin |
||||
|
from django.contrib.auth.models import Group |
||||
|
from django_reverse_admin import ReverseModelAdmin |
||||
|
import seminar.models as m |
||||
|
|
||||
|
|
||||
|
@admin.register(m.Osoba) |
||||
|
class OsobaAdmin(admin.ModelAdmin): |
||||
|
actions = ['synchronizuj_maily', 'udelej_orgem'] |
||||
|
|
||||
|
def synchronizuj_maily(self, request, queryset): |
||||
|
for o in queryset: |
||||
|
if o.user is not None: |
||||
|
u = o.user |
||||
|
u.email = o.email |
||||
|
u.save() |
||||
|
self.message_user(request, "E-maily synchronizovány.") |
||||
|
synchronizuj_maily.short_description = "Synchronizuj vybraným osobám e-maily do uživatelů" |
||||
|
|
||||
|
def udelej_orgem(self,request,queryset): |
||||
|
org_group = Group.objects.get(name='org') |
||||
|
print(queryset) |
||||
|
for o in queryset: |
||||
|
user = o.user |
||||
|
print(user) |
||||
|
user.groups.add(org_group) |
||||
|
user.is_staff = True |
||||
|
user.save() |
||||
|
org = m.Organizator.objects.create(osoba=o) |
||||
|
org.save() |
||||
|
udelej_orgem.short_description = "Udělej vybraných osob organizátory" |
||||
|
|
||||
|
@admin.register(m.Organizator) |
||||
|
class OrganizatorAdmin(admin.ModelAdmin): |
||||
|
search_fields = ['osoba__jmeno', 'osoba__prijmeni', 'osoba__prezdivka'] |
||||
|
|
||||
|
class OsobaInline(admin.TabularInline): |
||||
|
model = m.Osoba |
||||
|
|
||||
|
@admin.register(m.Resitel) |
||||
|
class ResitelAdmin(ReverseModelAdmin): |
||||
|
search_fields = ['osoba__jmeno', 'osoba__prijmeni', 'osoba__prezdivka'] |
||||
|
ordering = ('osoba__jmeno','osoba__prijmeni') |
||||
|
inline_type = 'stacked' |
||||
|
inline_reverse = ['osoba'] |
||||
|
|
||||
|
admin.site.register(m.Skola) |
||||
|
admin.site.register(m.Prijemce) |
@ -0,0 +1,5 @@ |
|||||
|
from django.apps import AppConfig |
||||
|
|
||||
|
|
||||
|
class PersonalniConfig(AppConfig): |
||||
|
name = 'personalni' |
@ -0,0 +1,221 @@ |
|||||
|
from django import forms |
||||
|
from dal import autocomplete |
||||
|
from django.contrib.auth.forms import PasswordResetForm |
||||
|
from django.core.exceptions import ObjectDoesNotExist |
||||
|
from django.contrib.auth.models import User |
||||
|
|
||||
|
from seminar.models import Skola, Resitel, Osoba |
||||
|
|
||||
|
from datetime import date |
||||
|
import logging |
||||
|
|
||||
|
# pro přidání políčka do formuláře je potřeba |
||||
|
# - mít v modelu tu položku, kterou chci upravovat |
||||
|
# - přidat do views (prihlaskaView, resitelEditView) |
||||
|
# - přidat do forms |
||||
|
# - includovat do html |
||||
|
|
||||
|
class DateInput(forms.DateInput): |
||||
|
# aby se datum dalo vybírat z kalendáře |
||||
|
input_type = 'date' |
||||
|
|
||||
|
class TelInput(forms.TextInput): |
||||
|
# tohle je možná k niřemu, ale alepsoň to mění input type a nic to nekazí |
||||
|
input_type = 'tel' |
||||
|
input_pattern="^[+]?[()/0-9. -]{9,}$" |
||||
|
|
||||
|
|
||||
|
class PrihlaskaForm(PasswordResetForm): |
||||
|
username = forms.CharField(label='Přihlašovací jméno', |
||||
|
max_length=256, |
||||
|
required=True, |
||||
|
help_text='Tímto jménem se následně budeš přihlašovat pro odevzdání řešení a další činnosti v semináři') |
||||
|
|
||||
|
jmeno = forms.CharField(label='Jméno', max_length=256, required=True) |
||||
|
prijmeni = forms.CharField(label='Příjmení', max_length=256, required=True) |
||||
|
pohlavi_muz = forms.ChoiceField(label='Pohlaví', |
||||
|
choices = ((True,'muž'),(False,'žena')), required=True) |
||||
|
email = forms.EmailField(label='E-mail',max_length=256, required=True) |
||||
|
telefon = forms.CharField(widget=TelInput(),label='Telefon',max_length=256, required=False) |
||||
|
datum_narozeni = forms.DateField(widget=DateInput(),label='Datum narození', required=False) |
||||
|
ulice = forms.CharField(label='Ulice a číslo popisné', max_length=256, required=False) |
||||
|
mesto = forms.CharField(label='Město', max_length=256, required=False) |
||||
|
psc = forms.CharField(label='PSČ', max_length=32, required=False) |
||||
|
stat = forms.ChoiceField(label='Stát', |
||||
|
choices = (('CZ', 'Česká Republika'), |
||||
|
('SK', 'Slovenská Republika'), |
||||
|
('other', 'Jiné')), |
||||
|
required=False) |
||||
|
stat_text = forms.CharField(label='Stát', max_length=256, required=False) |
||||
|
|
||||
|
skola = forms.ModelChoiceField(label="Škola", |
||||
|
queryset=Skola.objects.all(), |
||||
|
widget=autocomplete.ModelSelect2( |
||||
|
url='autocomplete_skola', |
||||
|
attrs = {'data-placeholder--id': '-1', |
||||
|
'data-placeholder--text' : '---', |
||||
|
'data-allow-clear': 'true'}) |
||||
|
,required=False) |
||||
|
|
||||
|
skola_nazev = forms.CharField(label='Název školy', max_length=256, required=False) |
||||
|
skola_adresa = forms.CharField(label='Adresa školy', max_length=256, required=False) |
||||
|
|
||||
|
# trida = forms.CharField(label='Třída',max_length=10, required=True) |
||||
|
|
||||
|
rok_maturity = forms.IntegerField( |
||||
|
label='Rok maturity', |
||||
|
min_value=date.today().year, |
||||
|
max_value=date.today().year+8, |
||||
|
required=True) |
||||
|
zasilat = forms.ChoiceField(label='Kam zasílat čísla a řešení',choices = Resitel.ZASILAT_CHOICES, required=True) |
||||
|
zasilat_cislo_emailem = forms.BooleanField(label='Chci dostávat e-mailem upozornění na vydání nového čísla', required=False) |
||||
|
|
||||
|
gdpr = forms.BooleanField(label='Souhlasím se zpracováním osobních údajů', required=True) |
||||
|
spam = forms.BooleanField(label='Souhlasím se zasíláním materiálů od MFF UK', required=False) |
||||
|
|
||||
|
def clean_username(self): |
||||
|
err_logger = logging.getLogger('seminar.prihlaska.problem') |
||||
|
username = self.cleaned_data.get('username') |
||||
|
try: |
||||
|
User.objects.get(username=username) |
||||
|
msg = "Username {} exists".format(username) |
||||
|
err_logger.info(msg) |
||||
|
raise forms.ValidationError('Přihlašovací jméno je již použito') |
||||
|
|
||||
|
except ObjectDoesNotExist: |
||||
|
pass |
||||
|
return username |
||||
|
|
||||
|
def clean_email(self): |
||||
|
err_logger = logging.getLogger('seminar.prihlaska.problem') |
||||
|
email = self.cleaned_data.get('email') |
||||
|
try: |
||||
|
osoba = Osoba.objects.get(email=email) |
||||
|
msg = "Email {} exists".format(email) |
||||
|
if osoba.user is not None: |
||||
|
err_logger.info(msg) |
||||
|
raise forms.ValidationError('E-mail je již použit') |
||||
|
else: |
||||
|
msg += ', but currently has no User, so allowing registration.' |
||||
|
err_logger.info(msg) |
||||
|
|
||||
|
except ObjectDoesNotExist: |
||||
|
pass |
||||
|
return email |
||||
|
|
||||
|
|
||||
|
def clean(self): |
||||
|
super().clean() |
||||
|
|
||||
|
err_logger = logging.getLogger('seminar.prihlaska.problem') |
||||
|
|
||||
|
data = self.cleaned_data |
||||
|
if data.get('stat') != 'other' and data.get('stat_text') != '': |
||||
|
self.add_error('stat',forms.ValidationError('Nelze mít vybraný stát z menu a zároven zapsaný textem')) |
||||
|
if data.get('skola') and (data.get('skola_nazev') or data.get('skola_adresa')): |
||||
|
self.add_error('skola',forms.ValidationError('Pokud je škola v seznamu, nevypisujte ji ručně, pokud není, zrušte výběr ze seznamu (křížek vpravo)')) |
||||
|
if not data.get('skola'): |
||||
|
if data.get('skola_nazev')=='' and data.get('skola_adresa')=='': |
||||
|
self.add_error('skola',forms.ValidationError('Je nutné vyplnit školu')) |
||||
|
elif data.get('skola_nazev')=='': |
||||
|
self.add_error('skola_nazev',forms.ValidationError('Je nutné vyplnit název školy')) |
||||
|
elif data.get('skola_adresa')=='': |
||||
|
self.add_error('skola_adresa',forms.ValidationError('Je nutné vyplnit adresu školy')) |
||||
|
|
||||
|
|
||||
|
class ProfileEditForm(forms.Form): |
||||
|
username = forms.CharField(label='Přihlašovací jméno', |
||||
|
max_length=256, |
||||
|
required=False, |
||||
|
disabled=True) |
||||
|
|
||||
|
jmeno = forms.CharField(label='Jméno', max_length=256, required=True) |
||||
|
prijmeni = forms.CharField(label='Příjmení', max_length=256, required=True) |
||||
|
pohlavi_muz = forms.ChoiceField(label='Pohlaví', |
||||
|
choices = ((True,'muž'),(False,'žena')), required=True) |
||||
|
email = forms.EmailField(label='E-mail',max_length=256, required=True) |
||||
|
telefon = forms.CharField(widget=TelInput(),label='Telefon',max_length=256, required=False) |
||||
|
datum_narozeni = forms.DateField(widget=DateInput(),label='Datum narození', required=False) |
||||
|
ulice = forms.CharField(label='Ulice', max_length=256, required=False) |
||||
|
mesto = forms.CharField(label='Město', max_length=256, required=False) |
||||
|
psc = forms.CharField(label='PSČ', max_length=32, required=False) |
||||
|
stat = forms.ChoiceField(label='Stát', |
||||
|
choices = (('CZ', 'Česká republika'), |
||||
|
('SK', 'Slovenská republika'), |
||||
|
('other', 'Jiné')), |
||||
|
required=False) |
||||
|
stat_text = forms.CharField(label='Stát', max_length=256, required=False) |
||||
|
|
||||
|
skola = forms.ModelChoiceField(label="Škola", |
||||
|
queryset=Skola.objects.all(), |
||||
|
widget=autocomplete.ModelSelect2( |
||||
|
url='autocomplete_skola', |
||||
|
attrs = {'data-placeholder--id': '-1', |
||||
|
'data-placeholder--text' : '---', |
||||
|
'data-allow-clear': 'true'}) |
||||
|
,required=False) |
||||
|
|
||||
|
skola_nazev = forms.CharField(label='Název školy', max_length=256, required=False) |
||||
|
skola_adresa = forms.CharField(label='Adresa školy', max_length=256, required=False) |
||||
|
|
||||
|
# trida = forms.CharField(label='Třída',max_length=10, required=True) |
||||
|
|
||||
|
rok_maturity = forms.IntegerField( |
||||
|
label='Rok maturity', |
||||
|
min_value=date.today().year, |
||||
|
max_value=date.today().year+8, |
||||
|
required=True) |
||||
|
zasilat = forms.ChoiceField(label='Kam zasílat čísla a řešení',choices = Resitel.ZASILAT_CHOICES, required=True) |
||||
|
zasilat_cislo_emailem = forms.BooleanField(label='Chci dostávat email s upozorněním na vydání nového čísla', required=False) |
||||
|
|
||||
|
spam = forms.BooleanField(label='Souhlasím se zasíláním materiálů od MFF UK', required=False) |
||||
|
# def clean_username(self): |
||||
|
# err_logger = logging.getLogger('seminar.prihlaska.problem') |
||||
|
# username = self.cleaned_data.get('username') |
||||
|
# try: |
||||
|
# User.objects.get(username=username) |
||||
|
# msg = "Username {} exists".format(username) |
||||
|
# err_logger.info(msg) |
||||
|
# raise forms.ValidationError('Přihlašovací jméno je již použito') |
||||
|
# |
||||
|
# except ObjectDoesNotExist: |
||||
|
# pass |
||||
|
# return username |
||||
|
# |
||||
|
def clean_email(self): |
||||
|
err_logger = logging.getLogger('seminar.prihlaska.problem') |
||||
|
email = self.cleaned_data.get('email') |
||||
|
try: |
||||
|
Osoba.objects.exclude(user__username=self.username).get(email=email) |
||||
|
msg = "Email {} exists (in edit)".format(email) |
||||
|
err_logger.info(msg) |
||||
|
raise forms.ValidationError('Email je již použit') |
||||
|
|
||||
|
except ObjectDoesNotExist: |
||||
|
pass |
||||
|
return email |
||||
|
#def clean(self): |
||||
|
# super().clean() |
||||
|
# |
||||
|
# err_logger = logging.getLogger('seminar.prihlaska.problem') |
||||
|
|
||||
|
# data = self.cleaned_data |
||||
|
# if data.get('password') != data.get('password_check'): |
||||
|
# self.add_error('password_check',forms.ValidationError('Hesla se neshodují')) |
||||
|
# if data.get('stat') != '' and data.get('stat_text') != '': |
||||
|
# self.add_error('stat',forms.ValidationError('Nelze mít vybraný stát z menu a zároven zapsaný textem')) |
||||
|
# if data.get('skola') and (data.get('skola_nazev') or data.get('skola_adresa')): |
||||
|
# self.add_error('skola',forms.ValidationError('Pokud je škola v seznamu, nevypisujte ji ručně, pokud není, zrušte výběr ze seznamu (křížek vpravo)')) |
||||
|
# if not data.get('skola'): |
||||
|
# if data.get('skola_nazev')=='' and data.get('skola_adresa')=='': |
||||
|
# self.add_error('skola',forms.ValidationError('Je nutné vyplnit školu')) |
||||
|
# elif data.get('skola_nazev')=='': |
||||
|
# self.add_error('skola_nazev',forms.ValidationError('Je nutné vyplnit název školy')) |
||||
|
# elif data.get('skola_adresa')=='': |
||||
|
# self.add_error('skola_adresa',forms.ValidationError('Je nutné vyplnit adresu školy')) |
||||
|
|
||||
|
|
||||
|
class PoMaturiteProfileEditForm(ProfileEditForm): |
||||
|
rok_maturity = forms.IntegerField( |
||||
|
label='Rok maturity', |
||||
|
required=True) |
@ -0,0 +1,105 @@ |
|||||
|
{% extends "base.html" %} |
||||
|
{% load staticfiles %} |
||||
|
|
||||
|
{% block script %} |
||||
|
<script src="{% static 'personalni/prihlaska.js' %}"></script> |
||||
|
{% endblock %} |
||||
|
|
||||
|
<!-- |
||||
|
|
||||
|
# pro přidání políčka do formuláře je potřeba |
||||
|
# - mít v modelu tu položku, kterou chci upravovat |
||||
|
# - přidat do views (prihlaskaView, resitelEditView) |
||||
|
# - přidat do forms |
||||
|
# - includovat do html |
||||
|
|
||||
|
--> |
||||
|
|
||||
|
{% block content %} |
||||
|
<h1> |
||||
|
{% block nadpis1a %}{% block nadpis1b %} |
||||
|
Změna osobních údajů |
||||
|
{% endblock %}{% endblock %} |
||||
|
</h1> |
||||
|
<form action="{% url 'seminar_resitel_edit' %}" method="post"> |
||||
|
{% csrf_token %} |
||||
|
{{form.non_field_errors}} |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<h4> |
||||
|
Přihlašovací údaje |
||||
|
</h4> |
||||
|
<table class="form"> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.username %} |
||||
|
</table> |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<h4> |
||||
|
Osobní údaje |
||||
|
</h4> |
||||
|
<table class="form"> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.jmeno %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.prijmeni %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.pohlavi_muz%} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.email %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.telefon %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.datum_narozeni %} |
||||
|
</table> |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<h4> |
||||
|
Bydliště |
||||
|
</h4> |
||||
|
<table class="form"> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.ulice %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.mesto %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.psc %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.stat %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.stat_text id="id_li_stat_text"%} |
||||
|
</table> |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<h4> |
||||
|
Škola |
||||
|
</h4> |
||||
|
<table class="form"> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.skola %} |
||||
|
<tr><td colspan="2" ><button id="id_skola_text_button" type="button">Škola není v seznamu</button></td></tr> |
||||
|
<tr><td id="id_li_skola_vypln" colspan="2">Vyplň prosím celý název a adresu školy.</td></tr> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.skola_nazev id="id_li_skola_nazev" %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.skola_adresa id="id_li_skola_adresa" %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.rok_maturity %} |
||||
|
</table> |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<h4> |
||||
|
Pošta |
||||
|
</h4> |
||||
|
<table class="form"> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.zasilat %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.zasilat_cislo_emailem %} |
||||
|
</table> |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<h4> |
||||
|
Zasílání propagačních materiálů |
||||
|
</h4> |
||||
|
<table class="form"> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.spam %} |
||||
|
</table> |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<input type="submit" value="Změnit"> |
||||
|
</form> |
||||
|
<script> |
||||
|
$("#id_stat").on("change",addrCountryChanged); |
||||
|
$("#id_skola_text_button").on("click",schoolNotInList); |
||||
|
</script> |
||||
|
{% endblock %} |
@ -0,0 +1,123 @@ |
|||||
|
{% extends "base.html" %} |
||||
|
{% load staticfiles %} |
||||
|
|
||||
|
{% block script %} |
||||
|
<script src="{% static 'personalni/prihlaska.js' %}"></script> |
||||
|
{% endblock %} |
||||
|
|
||||
|
<!-- |
||||
|
|
||||
|
# pro přidání políčka do formuláře je potřeba |
||||
|
# - mít v modelu tu položku, kterou chci upravovat |
||||
|
# - přidat do views (prihlaskaView, resitelEditView) |
||||
|
# - přidat do forms |
||||
|
# - includovat do html |
||||
|
|
||||
|
--> |
||||
|
|
||||
|
{% block content %} |
||||
|
<h1> |
||||
|
{% block nadpis1a %}{% block nadpis1b %} |
||||
|
Přihláška do semináře |
||||
|
{% endblock %}{% endblock %} |
||||
|
</h1> |
||||
|
|
||||
|
<p><b>Tučně</b> popsaná pole jsou povinná.</p> |
||||
|
|
||||
|
<form action="{% url 'seminar_prihlaska' %}" method="post"> |
||||
|
{% csrf_token %} |
||||
|
{{form.non_field_errors}} |
||||
|
|
||||
|
|
||||
|
<hr> |
||||
|
<h4> |
||||
|
Přihlašovací údaje |
||||
|
</h4> |
||||
|
<table class="form"> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.username %} |
||||
|
{# {% include "personalni/udaje/prihlaska_field.html" with field=form.password %}#} |
||||
|
{# {% include "personalni/udaje/prihlaska_field.html" with field=form.password_check %}#} |
||||
|
</table> |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<h4> |
||||
|
Osobní údaje |
||||
|
</h4> |
||||
|
<table class="form"> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.jmeno %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.prijmeni %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.pohlavi_muz%} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.email %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.telefon %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.datum_narozeni %} |
||||
|
</table> |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<h4> |
||||
|
Bydliště |
||||
|
</h4> |
||||
|
<table class="form"> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.ulice %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.mesto %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.psc %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.stat %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.stat_text id="id_li_stat_text"%} |
||||
|
</table> |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<h4> |
||||
|
Škola |
||||
|
</h4> |
||||
|
<table class="form"> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.skola %} |
||||
|
<tr><td colspan="2" ><button id="id_skola_text_button" type="button">Škola není v seznamu</button></td></tr> |
||||
|
<tr><td id="id_li_skola_vypln" colspan="2">Vyplň prosím celý název a adresu školy.</td></tr> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.skola_nazev id="id_li_skola_nazev" %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.skola_adresa id="id_li_skola_adresa" %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.rok_maturity %} |
||||
|
</table> |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<h4> |
||||
|
Pošta |
||||
|
</h4> |
||||
|
<table class="form"> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.zasilat %} |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.zasilat_cislo_emailem %} |
||||
|
</table> |
||||
|
<hr> |
||||
|
|
||||
|
<h4> |
||||
|
GDPR |
||||
|
</h4> |
||||
|
{% include "personalni/udaje/gdpr.html" %} |
||||
|
<table class="form"> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.gdpr %} |
||||
|
</table> |
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<h4> |
||||
|
Zasílání propagačních materiálů |
||||
|
</h4> |
||||
|
<table class="form"> |
||||
|
{% include "personalni/udaje/prihlaska_field.html" with field=form.spam %} |
||||
|
</table> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<hr> |
||||
|
|
||||
|
<input type="submit" value="Odeslat"> |
||||
|
</form> |
||||
|
<script> |
||||
|
$("#id_stat").on("change",addrCountryChanged); |
||||
|
$("#id_skola_text_button").on("click",schoolNotInList); |
||||
|
</script> |
||||
|
|
||||
|
|
||||
|
{% endblock %} |
@ -0,0 +1,24 @@ |
|||||
|
from django.urls import path |
||||
|
from django.contrib.auth.decorators import login_required |
||||
|
from . import views |
||||
|
from seminar.utils import org_required |
||||
|
|
||||
|
urlpatterns = [ |
||||
|
path( |
||||
|
'org/rozcestnik/', |
||||
|
org_required(views.OrgoRozcestnikView.as_view()), |
||||
|
name='seminar_org_rozcestnik' |
||||
|
), |
||||
|
|
||||
|
path('prihlaska/', views.prihlaskaView, name='seminar_prihlaska'), |
||||
|
|
||||
|
path( |
||||
|
'resitel/osobni-udaje/', |
||||
|
login_required(views.resitelEditView), |
||||
|
name='seminar_resitel_edit' |
||||
|
), |
||||
|
|
||||
|
# Obecný view na profil -- orgům dá rozcestník, řešitelům jejich stránku |
||||
|
path('profil/', views.profilView, name='profil'), |
||||
|
|
||||
|
] |
@ -0,0 +1,306 @@ |
|||||
|
from django.shortcuts import render |
||||
|
from django.urls import reverse |
||||
|
from django.views import generic |
||||
|
from django.db.models import Q |
||||
|
from django.views.decorators.debug import sensitive_post_parameters |
||||
|
from django.views.generic.base import TemplateView |
||||
|
from django.contrib.auth.models import User, Permission, Group |
||||
|
from django.contrib.auth.mixins import LoginRequiredMixin |
||||
|
from django.db import transaction |
||||
|
|
||||
|
import seminar.models as s |
||||
|
import seminar.models as m |
||||
|
from .forms import PrihlaskaForm, ProfileEditForm, PoMaturiteProfileEditForm |
||||
|
|
||||
|
from datetime import date |
||||
|
import logging |
||||
|
|
||||
|
from seminar.views import formularOKView |
||||
|
from various.autentizace.views import LoginView |
||||
|
from various.autentizace.utils import posli_reset_hesla |
||||
|
|
||||
|
from django.forms.models import model_to_dict |
||||
|
|
||||
|
|
||||
|
class OrgoRozcestnikView(TemplateView): |
||||
|
""" Zobrazí organizátorský rozcestník.""" |
||||
|
|
||||
|
template_name = 'personalni/profil/orgorozcestnik.html' |
||||
|
|
||||
|
def get_context_data(self, **kwargs): |
||||
|
context = super().get_context_data(**kwargs) |
||||
|
context['posledni_soustredeni'] = s.Soustredeni.objects.order_by('-datum_konce').first() |
||||
|
nastaveni = s.Nastaveni.objects.first() |
||||
|
aktualni_rocnik = nastaveni.aktualni_rocnik |
||||
|
context['posledni_cislo_url'] = nastaveni.aktualni_cislo.verejne_url() |
||||
|
# TODO možná chceme odkazovat na právě rozpracované číslo, a ne to poslední vydané |
||||
|
# pokud nechceme haluzit kód (= poradi) dalšího čísla, bude asi potřeba jít |
||||
|
# přes treenody (a dát si přitom pozor na MezicisloNode) |
||||
|
|
||||
|
neobodovana_reseni = s.Hodnoceni.objects.filter(body__isnull=True) |
||||
|
reseni_mimo_cislo = s.Hodnoceni.objects.filter(cislo_body__isnull=True) |
||||
|
context['pocet_neobodovanych_reseni'] = neobodovana_reseni.count() |
||||
|
context['pocet_reseni_mimo_cislo'] = reseni_mimo_cislo.count() |
||||
|
|
||||
|
u = self.request.user |
||||
|
os = s.Osoba.objects.get(user=u) |
||||
|
organizator = s.Organizator.objects.get(osoba=os) |
||||
|
|
||||
|
context['muj_pocet_neobodovanych_reseni'] = neobodovana_reseni.filter(Q(problem__garant=organizator) | Q(problem__autor=organizator) | Q(problem__opravovatele__in=[organizator])).distinct().count() |
||||
|
context['muj_pocet_reseni_mimo_cislo'] = reseni_mimo_cislo.filter(Q(problem__garant=organizator) | Q(problem__autor=organizator) | Q(problem__opravovatele__in=[organizator])).count() |
||||
|
|
||||
|
#FIXME: přidat stav='STAV_ZADANY' |
||||
|
temata = s.Tema.objects.filter(Q(garant=organizator) | Q(autor=organizator) | Q(opravovatele__in=[organizator]), |
||||
|
rocnik=aktualni_rocnik).distinct() |
||||
|
ulohy = s.Uloha.objects.filter(Q(garant=organizator) | Q(autor=organizator) | Q(opravovatele__in=[organizator]), |
||||
|
cislo_zadani__rocnik=aktualni_rocnik).distinct() |
||||
|
clanky = s.Clanek.objects.filter(Q(garant=organizator) | Q(autor=organizator) | Q(opravovatele__in=[organizator]), |
||||
|
cislo__rocnik=aktualni_rocnik).distinct() |
||||
|
|
||||
|
context['temata'] = temata |
||||
|
context['ulohy'] = ulohy |
||||
|
context['clanky'] = clanky |
||||
|
context['organizator'] = organizator |
||||
|
return context |
||||
|
|
||||
|
#content_type = 'text/plain; charset=UTF8' |
||||
|
#XXX |
||||
|
|
||||
|
|
||||
|
class ResitelView(LoginRequiredMixin,generic.DetailView): |
||||
|
model = s.Resitel |
||||
|
template_name = 'personalni/profil/resitel.html' |
||||
|
|
||||
|
def get_object(self, queryset=None): |
||||
|
print(self.request.user) |
||||
|
return s.Resitel.objects.get(osoba__user=self.request.user) |
||||
|
|
||||
|
### Formulare |
||||
|
|
||||
|
# pro přidání políčka do formuláře je potřeba |
||||
|
# - mít v modelu tu položku, kterou chci upravovat |
||||
|
# - přidat do views (prihlaskaView, resitelEditView) |
||||
|
# - přidat do forms |
||||
|
# - includovat do html |
||||
|
|
||||
|
def prihlaska_log_gdpr_safe(logger, gdpr_logger, msg, form_data): |
||||
|
msg = "{}, form_hash:{}".format(msg,hash(frozenset(form_data.items))) |
||||
|
logger.warn(msg) |
||||
|
gdpr_logger.warn(msg+", form:{}".format(form_data)) |
||||
|
|
||||
|
|
||||
|
@sensitive_post_parameters('jmeno', 'prijmeni', 'email', 'telefon', 'datum_narozeni', 'ulice', 'mesto', 'psc', 'skola') |
||||
|
def resitelEditView(request): |
||||
|
err_logger = logging.getLogger('seminar.prihlaska.problem') |
||||
|
## Načtení objektů Osoba a Resitel patřících k aktuálně přihlášenému uživateli |
||||
|
u = request.user |
||||
|
osoba_edit = s.Osoba.objects.get(user=u) |
||||
|
if hasattr(osoba_edit,'resitel'): |
||||
|
resitel_edit = osoba_edit.resitel |
||||
|
else: |
||||
|
resitel_edit = None |
||||
|
user_edit = osoba_edit.user |
||||
|
## Vytvoření slovníku, kterým předvyplním formulář |
||||
|
prefill_1=model_to_dict(user_edit) |
||||
|
if resitel_edit: |
||||
|
prefill_2=model_to_dict(resitel_edit) |
||||
|
prefill_1.update(prefill_2) |
||||
|
prefill_3=model_to_dict(osoba_edit) |
||||
|
prefill_1.update(prefill_3) |
||||
|
if 'datum_narozeni' in prefill_1: |
||||
|
prefill_1['datum_narozeni'] = str(prefill_1['datum_narozeni']) |
||||
|
if 'rok_maturity' not in prefill_1 or prefill_1['rok_maturity'] < date.today().year: |
||||
|
form = PoMaturiteProfileEditForm(initial=prefill_1) |
||||
|
else: |
||||
|
form = ProfileEditForm(initial=prefill_1) |
||||
|
## Změna údajů a jejich uložení |
||||
|
if request.method == 'POST': |
||||
|
POST = request.POST.copy() |
||||
|
POST["username"] = osoba_edit.user.username |
||||
|
|
||||
|
if 'rok_maturity' not in prefill_1 or prefill_1['rok_maturity'] < date.today().year: |
||||
|
form = PoMaturiteProfileEditForm(POST) |
||||
|
else: |
||||
|
form = ProfileEditForm(POST) |
||||
|
form.username = user_edit.username |
||||
|
if form.is_valid(): |
||||
|
## Změny v osobě |
||||
|
fcd = form.cleaned_data |
||||
|
form_hash = hash(frozenset(fcd.items())) |
||||
|
form_logger = logging.getLogger('seminar.prihlaska.form') |
||||
|
form_logger.info("EDIT:" + str(fcd) + str(form_hash)) # TODO možná logovat jinak |
||||
|
osoba_edit.jmeno = fcd['jmeno'] |
||||
|
osoba_edit.prijmeni = fcd['prijmeni'] |
||||
|
osoba_edit.pohlavi_muz = fcd['pohlavi_muz'] |
||||
|
osoba_edit.email = fcd['email'] |
||||
|
osoba_edit.telefon = fcd['telefon'] |
||||
|
osoba_edit.ulice = fcd['ulice'] |
||||
|
osoba_edit.mesto = fcd['mesto'] |
||||
|
osoba_edit.psc = fcd['psc'] |
||||
|
osoba_edit.datum_narozeni = fcd['datum_narozeni'] |
||||
|
## Změny v osobě s podmínkami |
||||
|
if fcd.get('spam',False): |
||||
|
osoba_edit.datum_souhlasu_zasilani = date.today() |
||||
|
if fcd.get('stat','') in ('CZ','SK'): |
||||
|
osoba_edit.stat = fcd['stat'] |
||||
|
else: |
||||
|
## Neznámá země |
||||
|
msg = "Unknown country {}".format(fcd['stat_text']) |
||||
|
|
||||
|
if resitel_edit: |
||||
|
## Změny v řešiteli |
||||
|
resitel_edit.skola = fcd['skola'] |
||||
|
resitel_edit.rok_maturity = fcd['rok_maturity'] |
||||
|
resitel_edit.zasilat = fcd['zasilat'] |
||||
|
resitel_edit.zasilat_cislo_emailem = fcd['zasilat_cislo_emailem'] |
||||
|
if fcd.get('skola'): |
||||
|
resitel_edit.skola = fcd['skola'] |
||||
|
else: |
||||
|
# Unknown school - log it |
||||
|
msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa']) |
||||
|
resitel_edit.save() |
||||
|
osoba_edit.save() |
||||
|
return formularOKView(request, text=f'Údaje byly úspěšně uloženy. <a href="{reverse("profil")}">Vrátit se zpět na profil.</a>') |
||||
|
|
||||
|
return render(request, 'personalni/udaje/edit.html', {'form': form}) |
||||
|
|
||||
|
|
||||
|
@sensitive_post_parameters('jmeno', 'prijmeni', 'email', 'telefon', 'datum_narozeni', 'ulice', 'mesto', 'psc', 'skola') |
||||
|
def prihlaskaView(request): |
||||
|
generic_logger = logging.getLogger('seminar.prihlaska') |
||||
|
err_logger = logging.getLogger('seminar.prihlaska.problem') |
||||
|
form_logger = logging.getLogger('seminar.prihlaska.form') |
||||
|
if request.method == 'POST': |
||||
|
form = PrihlaskaForm(request.POST) |
||||
|
# TODO vyresit, co se bude v jakych situacich zobrazovat |
||||
|
if form.is_valid(): |
||||
|
generic_logger.info("Form valid") |
||||
|
fcd = form.cleaned_data |
||||
|
form_hash = hash(frozenset(fcd.items())) |
||||
|
form_logger.info(str(fcd) + str(form_hash)) # TODO možná logovat jinak |
||||
|
|
||||
|
with transaction.atomic(): |
||||
|
u = User.objects.create_user( |
||||
|
username=fcd['username'], |
||||
|
email = fcd['email']) |
||||
|
u.save() |
||||
|
resitel_perm = Permission.objects.filter(codename__exact='resitel').first() |
||||
|
u.user_permissions.add(resitel_perm) |
||||
|
resitel_grp = Group.objects.filter(name__exact='resitel').first() |
||||
|
u.groups.add(resitel_grp) |
||||
|
|
||||
|
o = s.Osoba( |
||||
|
jmeno = fcd['jmeno'], |
||||
|
prijmeni = fcd['prijmeni'], |
||||
|
pohlavi_muz = fcd['pohlavi_muz'], |
||||
|
email = fcd['email'], |
||||
|
telefon = fcd.get('telefon',''), |
||||
|
datum_narozeni = fcd.get('datum_narozeni',None), |
||||
|
datum_souhlasu_udaje = date.today(), |
||||
|
datum_registrace = date.today(), |
||||
|
ulice = fcd.get('ulice',''), |
||||
|
mesto = fcd.get('mesto',''), |
||||
|
psc = fcd.get('psc',''), |
||||
|
poznamka = str(fcd) |
||||
|
) |
||||
|
|
||||
|
if fcd.get('spam',False): |
||||
|
o.datum_souhlasu_zasilani = date.today() |
||||
|
if fcd.get('stat','') in ('CZ','SK'): |
||||
|
o.stat = fcd['stat'] |
||||
|
else: |
||||
|
# Unknown country - log it |
||||
|
msg = "Unknown country {}".format(fcd['stat_text']) |
||||
|
err_logger.warn(msg + str(form_hash)) |
||||
|
|
||||
|
|
||||
|
# Dovolujeme doregistraci uživatele pro existující mail, takže naopak chceme doplnit/aktualizovat údaje do stávajícího objektu |
||||
|
try: |
||||
|
orig_osoba = m.Osoba.objects.get(email=fcd['email']) |
||||
|
orig_osoba.poznamka += '\nDOREGISTRACE K EXISTUJÍCÍMU E-MAILU, diff níže.' |
||||
|
except m.Osoba.DoesNotExist: |
||||
|
# Trik: Budeme aktualizovat údaje nové osoby, takže se asi nic nezmění, ale fungovat to bude. |
||||
|
orig_osoba = o |
||||
|
|
||||
|
# Porovnání údajů |
||||
|
assert orig_osoba.user is None, "Právě-registrující-se osoba už má Uživatele!" |
||||
|
osoba_attrs = ['jmeno', 'prijmeni', 'pohlavi_muz', 'email', 'telefon', 'datum_narozeni', 'ulice', 'mesto', 'psc', 'stat', 'datum_souhlasu_udaje', 'datum_souhlasu_zasilani', 'datum_registrace'] |
||||
|
diffattrs = [] |
||||
|
for attr in osoba_attrs: |
||||
|
new = getattr(o, attr) |
||||
|
old = getattr(orig_osoba, attr) |
||||
|
if new != old: |
||||
|
orig_osoba.poznamka += f'\nRozdíl v {attr}: Původní {old}, nový {new}' |
||||
|
diffattrs.append(f'Osoba.{attr}') |
||||
|
setattr(orig_osoba, attr, new) |
||||
|
# Datum registrace chceme původní / nižší: |
||||
|
orig_osoba.datum_registrace = min(orig_osoba.datum_registrace, o.datum_registrace) |
||||
|
|
||||
|
# Od této chvíle dál je správná osoba ta "původní", novou podle formuláře si ale zachováme |
||||
|
o, o_form = orig_osoba, o |
||||
|
|
||||
|
|
||||
|
|
||||
|
o.save() |
||||
|
o.user = u |
||||
|
o.save() |
||||
|
|
||||
|
# Jednoduchá kvazi-kontrola duplicitních Osob |
||||
|
kolize = m.Osoba.objects.filter(jmeno=o.jmeno, prijmeni=o.prijmeni) |
||||
|
if kolize.count() > 1: # Jednu z nich jsme právě uložili |
||||
|
err_logger.warning(f'Zaregistrovala se osoba s kolizním jménem. ID osob: {[o.id for o in kolize]}') |
||||
|
|
||||
|
r = s.Resitel( |
||||
|
rok_maturity = fcd['rok_maturity'], |
||||
|
zasilat = fcd['zasilat'], |
||||
|
zasilat_cislo_emailem = fcd['zasilat_cislo_emailem'] |
||||
|
) |
||||
|
|
||||
|
if fcd.get('skola'): |
||||
|
r.skola = fcd['skola'] |
||||
|
else: |
||||
|
# Unknown school - log it |
||||
|
msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa']) |
||||
|
err_logger.warn(msg + str(form_hash)) |
||||
|
|
||||
|
# Porovnání údajů u řešitele |
||||
|
try: |
||||
|
orig_resitel = o.resitel |
||||
|
orig_resitel.poznamka += '\nDOREGISTRACE ŘEŠITELE, diff:' |
||||
|
except m.Resitel.DoesNotExist: |
||||
|
# Stejný trik: |
||||
|
orig_resitel = r |
||||
|
resitel_attrs = ['skola', 'rok_maturity', 'zasilat', 'zasilat_cislo_emailem'] |
||||
|
for attr in resitel_attrs: |
||||
|
new = getattr(r, attr) |
||||
|
old = getattr(orig_resitel, attr) |
||||
|
if new != old: |
||||
|
orig_resitel.poznamka += f'\nRozdíl v {attr}: Původní {old}, nový {new}' |
||||
|
diffattrs.append(f'Resitel.{attr}') |
||||
|
setattr(orig_resitel, attr, new) |
||||
|
r, r_form = orig_resitel, r |
||||
|
|
||||
|
r.osoba = o # Tohle by mělo být bezpečné… |
||||
|
r.save() |
||||
|
|
||||
|
if diffattrs: err_logger.warning(f'Different fields when matching Řešitel id {r.id} or Osoba id {o.id}: {diffattrs}') |
||||
|
|
||||
|
posli_reset_hesla(u, request) |
||||
|
return formularOKView(request, text='Na tvůj e-mail jsme právě poslali odkaz pro nastavení hesla.') |
||||
|
|
||||
|
# if a GET (or any other method) we'll create a blank form |
||||
|
else: |
||||
|
form = PrihlaskaForm() |
||||
|
|
||||
|
return render(request, 'personalni/udaje/prihlaska.html', {'form': form}) |
||||
|
|
||||
|
|
||||
|
# Jen hloupé rozhazovátko |
||||
|
def profilView(request): |
||||
|
user = request.user |
||||
|
if user.has_perm('auth.org'): |
||||
|
return OrgoRozcestnikView.as_view()(request) |
||||
|
if user.has_perm('auth.resitel'): |
||||
|
return ResitelView.as_view()(request) |
||||
|
else: |
||||
|
return LoginView.as_view()(request) |
@ -1,2 +1,4 @@ |
|||||
from .models_all import * |
from .models_all import * |
||||
from .odevzdavatko import * |
from .odevzdavatko import * |
||||
|
from .base import * |
||||
|
from .personalni import * |
||||
|
@ -0,0 +1,22 @@ |
|||||
|
from django.urls import reverse |
||||
|
from django.db import models |
||||
|
|
||||
|
|
||||
|
class SeminarModelBase(models.Model): |
||||
|
|
||||
|
class Meta: |
||||
|
abstract = True |
||||
|
|
||||
|
def verejne(self): |
||||
|
return False |
||||
|
|
||||
|
# def get_absolute_url(self): |
||||
|
# return "https://" + str(get_current_site(None)) + self.verejne_url() |
||||
|
|
||||
|
def admin_url(self): |
||||
|
model_name = self.__class__.__name__.lower() |
||||
|
return reverse('admin:seminar_{}_change'.format(model_name), args=(self.id, )) |
||||
|
|
||||
|
# def verejne_url(self): |
||||
|
# return None |
||||
|
|
@ -0,0 +1,438 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
import logging |
||||
|
|
||||
|
from django.db import models |
||||
|
from django.utils import timezone |
||||
|
from django.conf import settings |
||||
|
from django.core.exceptions import ValidationError |
||||
|
from imagekit.models import ImageSpecField, ProcessedImageField |
||||
|
from imagekit.processors import ResizeToFit, Transpose |
||||
|
|
||||
|
from django_countries.fields import CountryField |
||||
|
|
||||
|
from reversion import revisions as reversion |
||||
|
|
||||
|
from .base import SeminarModelBase |
||||
|
|
||||
|
logger = logging.getLogger(__name__) |
||||
|
|
||||
|
|
||||
|
@reversion.register(ignore_duplicates=True) |
||||
|
class Osoba(SeminarModelBase): |
||||
|
|
||||
|
class Meta: |
||||
|
db_table = 'seminar_osoby' |
||||
|
verbose_name = 'Osoba' |
||||
|
verbose_name_plural = 'Osoby' |
||||
|
ordering = ['prijmeni','jmeno'] |
||||
|
|
||||
|
id = models.AutoField(primary_key = True) |
||||
|
|
||||
|
jmeno = models.CharField('jméno', max_length=256) |
||||
|
|
||||
|
prijmeni = models.CharField('příjmení', max_length=256) |
||||
|
|
||||
|
prezdivka = models.CharField('přezdívka', blank=True, null=True, max_length=256) |
||||
|
|
||||
|
# User, pokud má na webu účet |
||||
|
user = models.OneToOneField(settings.AUTH_USER_MODEL, blank=True, null=True, |
||||
|
verbose_name='uživatel', on_delete=models.DO_NOTHING) |
||||
|
|
||||
|
# Pohlaví. Že ho neznáme se snad nestane (a ušetří to práci při programování) |
||||
|
pohlavi_muz = models.BooleanField('pohlaví (muž)', default=False) |
||||
|
|
||||
|
email = models.EmailField('e-mail', max_length=256, blank=True, default='') |
||||
|
|
||||
|
telefon = models.CharField('telefon', max_length=256, blank=True, default='') |
||||
|
|
||||
|
datum_narozeni = models.DateField('datum narození', blank=True, null=True) |
||||
|
|
||||
|
# NULL dokud nedali souhlas |
||||
|
datum_souhlasu_udaje = models.DateField('datum souhlasu (údaje)', blank=True, null=True, |
||||
|
help_text='Datum souhlasu se zpracováním osobních údajů') |
||||
|
|
||||
|
# NULL dokud nedali souhlas |
||||
|
datum_souhlasu_zasilani = models.DateField('datum souhlasu (spam)', blank=True, null=True, |
||||
|
help_text='Datum souhlasu se zasíláním MFF materiálů') |
||||
|
|
||||
|
# Alespoň odhad (rok či i měsíc) |
||||
|
datum_registrace = models.DateField('datum registrace do semináře', default=timezone.now) |
||||
|
|
||||
|
# Ulice může být i jen číslo |
||||
|
ulice = models.CharField('ulice', max_length=256, blank=True, default='') |
||||
|
|
||||
|
mesto = models.CharField('město', max_length=256, blank=True, default='') |
||||
|
|
||||
|
psc = models.CharField('PSČ', max_length=32, blank=True, default='') |
||||
|
|
||||
|
# ISO 3166-1 dvojznakovy kod zeme velkym pismem (CZ, SK) |
||||
|
# Ekvivalentní s CharField(max_length=2, default='CZ', ...) |
||||
|
stat = CountryField('stát', default='CZ', |
||||
|
help_text='ISO 3166-1 kód země velkými písmeny (CZ, SK, ...)') |
||||
|
|
||||
|
poznamka = models.TextField('neveřejná poznámka', blank=True, |
||||
|
help_text='Neveřejná poznámka k osobě (plain text)') |
||||
|
|
||||
|
foto = ProcessedImageField(verbose_name='Fotografie osoby', |
||||
|
upload_to='image_osoby/velke/%Y/', null = True, blank = True, |
||||
|
help_text = 'Vlož fotografii osoby o libovolné velikosti', |
||||
|
processors=[ |
||||
|
Transpose(Transpose.AUTO), |
||||
|
ResizeToFit(500, 500, upscale=False) |
||||
|
], |
||||
|
options={'quality': 95}) |
||||
|
foto_male = ImageSpecField(source='foto', |
||||
|
processors=[ |
||||
|
ResizeToFit(200, 200, upscale=False) |
||||
|
], |
||||
|
options={'quality': 95}) |
||||
|
|
||||
|
# má OneToOneField nejvýše s: |
||||
|
# Resitel |
||||
|
# Prijemce |
||||
|
# Organizator |
||||
|
|
||||
|
def plne_jmeno(self): |
||||
|
return '{} {}'.format(self.jmeno, self.prijmeni) |
||||
|
|
||||
|
def inicial_krestni(self): |
||||
|
jmena = self.jmeno.split() |
||||
|
return " ".join(['{}.'.format(jmeno[0]) for jmeno in jmena]) |
||||
|
|
||||
|
def __str__(self): |
||||
|
return self.plne_jmeno() |
||||
|
|
||||
|
# Overridujeme save Osoby, aby když si změní e-mail, aby se projevil i v |
||||
|
# Userovi (a tak se dal poslat mail s resetem hesla) |
||||
|
def save(self, *args, **kwargs): |
||||
|
if self.user is not None: |
||||
|
u = self.user |
||||
|
# U svatého tučňáka, prosím ať tohle funguje. |
||||
|
# (Takhle se kódit asi nemá...) |
||||
|
u.email = self.email |
||||
|
u.save() |
||||
|
super().save() |
||||
|
|
||||
|
# |
||||
|
# Mělo by být částečně vytaženo z Aesopa |
||||
|
# viz https://ovvp.mff.cuni.cz/wiki/aesop/export-skol. |
||||
|
# |
||||
|
|
||||
|
@reversion.register(ignore_duplicates=True) |
||||
|
class Skola(SeminarModelBase): |
||||
|
|
||||
|
class Meta: |
||||
|
db_table = 'seminar_skoly' |
||||
|
verbose_name = 'Škola' |
||||
|
verbose_name_plural = 'Školy' |
||||
|
ordering = ['mesto', 'nazev'] |
||||
|
|
||||
|
# Interní ID |
||||
|
id = models.AutoField(primary_key = True) |
||||
|
|
||||
|
# Aesopi ID "izo:..." nebo "aesop:..." |
||||
|
# NULL znamená v exportu do aesopa "ufo" |
||||
|
aesop_id = models.CharField('Aesop ID', max_length=32, blank=True, default='', |
||||
|
help_text='Aesopi ID typu "izo:..." nebo "aesop:..."') |
||||
|
|
||||
|
# IZO školy (jen české školy) |
||||
|
izo = models.CharField('IZO', max_length=32, blank=True, |
||||
|
help_text='IZO školy (jen české školy)') |
||||
|
|
||||
|
# Celý název školy |
||||
|
nazev = models.CharField('název', max_length=256, |
||||
|
help_text='Celý název školy') |
||||
|
|
||||
|
# Zkraceny nazev pro zobrazení ve výsledkovce, volitelné. |
||||
|
# Není v Aesopovi, musíme vytvářet sami. |
||||
|
kratky_nazev = models.CharField('zkrácený název', max_length=256, blank=True, |
||||
|
help_text="Zkrácený název pro zobrazení ve výsledkovce") |
||||
|
|
||||
|
# Ulice může být jen číslo |
||||
|
ulice = models.CharField('ulice', max_length=256) |
||||
|
|
||||
|
mesto = models.CharField('město', max_length=256) |
||||
|
|
||||
|
psc = models.CharField('PSČ', max_length=32) |
||||
|
|
||||
|
# ISO 3166-1 dvojznakovy kod zeme velkym pismem (CZ, SK) |
||||
|
# Ekvivalentní s CharField(max_length=2, default='CZ', ...) |
||||
|
stat = CountryField('stát', default='CZ', |
||||
|
help_text='ISO 3166-1 kód země velkými písmeny (CZ, SK, ...)') |
||||
|
|
||||
|
# Jaké vzdělání škpla poskytuje? |
||||
|
je_zs = models.BooleanField('základní stupeň', default=True) |
||||
|
je_ss = models.BooleanField('střední stupeň', default=True) |
||||
|
|
||||
|
poznamka = models.TextField('neveřejná poznámka', blank=True, |
||||
|
help_text='Neveřejná poznámka ke škole (plain text)') |
||||
|
|
||||
|
kontaktni_osoba = models.ForeignKey(Osoba, verbose_name='Kontaktní osoba', |
||||
|
blank=True, null=True, on_delete=models.SET_NULL) |
||||
|
|
||||
|
def __str__(self): |
||||
|
return '{}, {}, {}'.format(self.nazev, self.ulice, self.mesto) |
||||
|
|
||||
|
class Prijemce(SeminarModelBase): |
||||
|
class Meta: |
||||
|
db_table = 'seminar_prijemce' |
||||
|
verbose_name = 'příjemce' |
||||
|
verbose_name_plural = 'příjemce' |
||||
|
|
||||
|
|
||||
|
# Interní ID |
||||
|
id = models.AutoField(primary_key = True) |
||||
|
|
||||
|
poznamka = models.TextField('neveřejná poznámka', blank=True, |
||||
|
help_text='Neveřejná poznámka k příemci čísel (plain text)') |
||||
|
|
||||
|
osoba = models.OneToOneField(Osoba, verbose_name='komu', blank=False, null=False, |
||||
|
help_text='Které osobě či na jakou adresu se mají zasílat čísla', |
||||
|
on_delete=models.CASCADE) |
||||
|
|
||||
|
# FIXME: možná chceme něco jako vazbu na osobu XOR školu a počet kusů k zaslání |
||||
|
# FIXME: a možná taky posílání na mail a možná taky přes něj chceme posílat i řešitelům |
||||
|
|
||||
|
def __str__(self): |
||||
|
return self.osoba.plne_jmeno() |
||||
|
|
||||
|
|
||||
|
@reversion.register(ignore_duplicates=True) |
||||
|
class Resitel(SeminarModelBase): |
||||
|
|
||||
|
class Meta: |
||||
|
db_table = 'seminar_resitele' |
||||
|
verbose_name = 'Řešitel' |
||||
|
verbose_name_plural = 'Řešitelé' |
||||
|
ordering = ['osoba'] |
||||
|
|
||||
|
# Interní ID |
||||
|
id = models.AutoField(primary_key = True) |
||||
|
|
||||
|
osoba = models.OneToOneField(Osoba, blank=False, null=False, verbose_name='osoba', |
||||
|
on_delete=models.PROTECT) |
||||
|
|
||||
|
|
||||
|
skola = models.ForeignKey(Skola, blank=True, null=True, verbose_name='škola', |
||||
|
on_delete=models.SET_NULL) |
||||
|
|
||||
|
# Očekávaný rok maturity a vyřazení z aktivních řešitelů |
||||
|
rok_maturity = models.IntegerField('rok maturity', blank=True, null=True) |
||||
|
|
||||
|
ZASILAT_DOMU = 'domu' |
||||
|
ZASILAT_DO_SKOLY = 'do_skoly' |
||||
|
ZASILAT_NIKAM = 'nikam' |
||||
|
ZASILAT_CHOICES = [ |
||||
|
(ZASILAT_DOMU, 'Domů'), |
||||
|
(ZASILAT_DO_SKOLY, 'Do školy'), |
||||
|
(ZASILAT_NIKAM, 'Nikam'), |
||||
|
] |
||||
|
|
||||
|
zasilat = models.CharField('kam zasílat', max_length=32, choices=ZASILAT_CHOICES, blank=False, default=ZASILAT_DOMU) |
||||
|
|
||||
|
zasilat_cislo_emailem = models.BooleanField('zasílat číslo emailem', help_text='True pokud chce řešitel dostávat číslo emailem', default=False) |
||||
|
|
||||
|
poznamka = models.TextField('neveřejná poznámka', blank=True, |
||||
|
help_text='Neveřejná poznámka k řešiteli (plain text)') |
||||
|
|
||||
|
|
||||
|
def export_row(self): |
||||
|
"Slovnik pro pouziti v AESOP exportu" |
||||
|
return { |
||||
|
'id': self.id, |
||||
|
'name': self.osoba.jmeno, |
||||
|
'surname': self.osoba.prijmeni, |
||||
|
'gender': 'M' if self.osoba.pohlavi_muz else 'F', |
||||
|
'born': self.osoba.datum_narozeni.isoformat() if self.osoba.datum_narozeni else '', |
||||
|
'email': self.osoba.email, |
||||
|
'end-year': self.rok_maturity or '', |
||||
|
|
||||
|
'street': self.osoba.ulice, |
||||
|
'town': self.osoba.mesto, |
||||
|
'postcode': self.osoba.psc, |
||||
|
'country': self.osoba.stat, |
||||
|
|
||||
|
'spam-flag': 'Y' if self.osoba.datum_souhlasu_zasilani else '', |
||||
|
'spam-date': self.osoba.datum_souhlasu_zasilani.isoformat() if self.osoba.datum_souhlasu_zasilani else '', |
||||
|
|
||||
|
'school': self.skola.aesop_id if self.skola else '', |
||||
|
'school-name': str(self.skola) if self.skola else 'Skola neni znama', |
||||
|
} |
||||
|
|
||||
|
def rocnik(self, rocnik): |
||||
|
"""Vrati skolni rocnik resitele pro zadany Rocnik. |
||||
|
Vraci '' pro neznamy rok maturity resitele, Z* pro ekvivalent ZŠ.""" |
||||
|
if self.rok_maturity is None: |
||||
|
return '' |
||||
|
rozdil = 5 - (self.rok_maturity - rocnik.prvni_rok) |
||||
|
if rozdil >= 1: |
||||
|
return str(rozdil) |
||||
|
else: |
||||
|
return 'Z' + str(rozdil + 9) |
||||
|
|
||||
|
def vsechny_body(self): |
||||
|
"Spočítá body odjakživa." |
||||
|
vsechna_reseni = self.reseni_set.all() |
||||
|
from .odevzdavatko import Hodnoceni |
||||
|
vsechna_hodnoceni = Hodnoceni.objects.filter( |
||||
|
reseni__in=vsechna_reseni) |
||||
|
return sum(h.body for h in list(vsechna_hodnoceni) if h.body is not None) |
||||
|
|
||||
|
|
||||
|
def get_titul(self, body=None): |
||||
|
"Vrati titul jako řetězec." |
||||
|
|
||||
|
# Nejprve si zadefinujeme titul |
||||
|
from enum import Enum |
||||
|
from functools import total_ordering |
||||
|
@total_ordering |
||||
|
class Titul(Enum): |
||||
|
""" Třída reprezentující možné tituly. Hodnoty jsou dvojice (dolní hranice, stringifikace). """ |
||||
|
nic = (0, '') |
||||
|
bc = (20, 'Bc.') |
||||
|
mgr = (50, 'Mgr.') |
||||
|
dr = (100, 'Dr.') |
||||
|
doc = (200, 'Doc.') |
||||
|
prof = (500, 'Prof.') |
||||
|
akad = (1000, 'Akad.') |
||||
|
|
||||
|
def __lt__(self, other): |
||||
|
return True if self.value[0] < other.value[0] else False |
||||
|
def __eq__(self, other): # Měla by být implicitní, ale klidně explicitně. |
||||
|
return True if self.value[0] == other.value[0] else False |
||||
|
|
||||
|
def __str__(self): |
||||
|
return self.value[1] |
||||
|
|
||||
|
@classmethod |
||||
|
def z_bodu(cls, body): |
||||
|
aktualni = cls.nic |
||||
|
# TODO: ověřit, že to funguje |
||||
|
for titul in cls: # Kdyžtak použít __members__.items() |
||||
|
if titul.value[0] <= body: |
||||
|
aktualni = titul |
||||
|
else: |
||||
|
break |
||||
|
return aktualni |
||||
|
|
||||
|
# Hledáme body v databázi |
||||
|
# V listopadu 2020 jsme se na filosofické schůzce shodli o změně hranic titulů: |
||||
|
# - body z 25. ročníku a dříve byly shledány dvakrát hodnotnějšími |
||||
|
# - proto se započítávají dvojnásobně a byly posunuté hranice titulů |
||||
|
# - staré tituly se ale nemají odebrat, pokud řešitel v t.č. minulém (26.) ročníku měl titul, má ho mít pořád. |
||||
|
from .odevzdavatko import Hodnoceni |
||||
|
hodnoceni_do_25_rocniku = Hodnoceni.objects.filter(cislo_body__rocnik__rocnik__lte=25,reseni__in=self.reseni_set.all()) |
||||
|
novejsi_hodnoceni = Hodnoceni.objects.filter(reseni__in=self.reseni_set.all()).difference(hodnoceni_do_25_rocniku) |
||||
|
|
||||
|
def body_z_hodnoceni(hh : list): |
||||
|
return sum(h.body for h in hh if h.body is not None) |
||||
|
|
||||
|
stare_body = body_z_hodnoceni(hodnoceni_do_25_rocniku) |
||||
|
if body is None: |
||||
|
nove_body = body_z_hodnoceni(novejsi_hodnoceni) |
||||
|
else: |
||||
|
# Zjistíme, kolik bodů jsou staré, tedy hodnotnější |
||||
|
nove_body = max(0, body - stare_body) # Všechny body nad počet původních hodnotnějších |
||||
|
stare_body = min(stare_body, body) # Skutečný počet hodnotnějších bodů |
||||
|
logicke_body = 2*stare_body + nove_body |
||||
|
|
||||
|
|
||||
|
# Titul se určí následovně: |
||||
|
# - Pokud se řeší body, které jsou starší, než do 26 ročníku (včetně), dáváme tituly postaru. |
||||
|
# - Jinak dáváme tituly po novu... |
||||
|
# - ... ale titul se nesmí odebrat, pokud se zmenšil. |
||||
|
def titul_do_26_rocniku(body): |
||||
|
""" Původní hranice bodů za tituly """ |
||||
|
if body < 10: |
||||
|
return Titul.nic |
||||
|
elif body < 20: |
||||
|
return Titul.bc |
||||
|
elif body < 50: |
||||
|
return Titul.mgr |
||||
|
elif body < 100: |
||||
|
return Titul.dr |
||||
|
elif body < 200: |
||||
|
return Titul.doc |
||||
|
elif body < 500: |
||||
|
return Titul.prof |
||||
|
else: |
||||
|
return Titul.akad |
||||
|
|
||||
|
from .odevzdavatko import Hodnoceni |
||||
|
hodnoceni_do_26_rocniku = Hodnoceni.objects.filter(cislo_body__rocnik__rocnik__lte=26,reseni__in=self.reseni_set.all()) |
||||
|
novejsi_body = body_z_hodnoceni( |
||||
|
Hodnoceni.objects.filter(reseni__in=self.reseni_set.all()) |
||||
|
.difference(hodnoceni_do_26_rocniku) |
||||
|
) |
||||
|
starsi_body = body_z_hodnoceni(hodnoceni_do_26_rocniku) |
||||
|
if body is not None: |
||||
|
# Ještě z toho vybereme ty správně staré body |
||||
|
novejsi_body = max(0, body - starsi_body) |
||||
|
starsi_body = min(starsi_body, body) |
||||
|
|
||||
|
# Titul pro 26. ročník |
||||
|
stary_titul = titul_do_26_rocniku(starsi_body) |
||||
|
# Titul podle aktuálních pravidel |
||||
|
novy_titul = Titul.z_bodu(logicke_body) |
||||
|
|
||||
|
if novejsi_body == 0: |
||||
|
# Žádné nové body -- titul podle starých pravidel |
||||
|
return str(stary_titul) |
||||
|
return str(max(novy_titul, stary_titul)) |
||||
|
|
||||
|
|
||||
|
def __str__(self): |
||||
|
return self.osoba.plne_jmeno() |
||||
|
|
||||
|
|
||||
|
@reversion.register(ignore_duplicates=True) |
||||
|
class Organizator(SeminarModelBase): |
||||
|
osoba = models.OneToOneField(Osoba, verbose_name='osoba', related_name='org', |
||||
|
help_text='osobní údaje organizátora', null=False, blank=False, |
||||
|
on_delete=models.PROTECT) |
||||
|
|
||||
|
vytvoreno = models.DateTimeField( |
||||
|
'Vytvořeno', |
||||
|
default=timezone.now, |
||||
|
blank=True, |
||||
|
editable=False |
||||
|
) |
||||
|
|
||||
|
organizuje_od = models.DateTimeField('Organizuje od', blank=True, null=True) |
||||
|
|
||||
|
organizuje_do = models.DateTimeField('Organizuje do', blank=True, null=True) |
||||
|
|
||||
|
studuje = models.CharField('Studium aj.', max_length = 256, |
||||
|
null = True, blank = True, |
||||
|
help_text="Např. 'Studuje Obecnou fyziku (Bc.), 3. ročník', " |
||||
|
"'Vystudovala Diskrétní modely a algoritmy (Mgr.)' nebo " |
||||
|
"'Přednáší na MFF'") |
||||
|
|
||||
|
strucny_popis_organizatora = models.TextField('Stručný popis organizátora', |
||||
|
null = True, blank = True) |
||||
|
|
||||
|
skola = models.CharField('Škola, kterou studuje', max_length = 256, null=True, blank=True, |
||||
|
help_text="Škola, např. MFF, VŠCHT, VUT, ... prostě aby se nemuselo psát do studuje" |
||||
|
"školu, ale jen obor, možnost zobrazit zvlášť") |
||||
|
|
||||
|
def clean(self): |
||||
|
if self.organizuje_od and self.organizuje_do and (self.organizuje_od > self.organizuje_do): |
||||
|
raise ValidationError("Organizátor nemůže skončit s organizováním dříve než začal!") |
||||
|
super().clean() |
||||
|
|
||||
|
def __str__(self): |
||||
|
if self.osoba.prezdivka: |
||||
|
return "{} '{}' {}".format(self.osoba.jmeno, |
||||
|
self.osoba.prezdivka, |
||||
|
self.osoba.prijmeni) |
||||
|
else: |
||||
|
return "{} {}".format(self.osoba.jmeno, self.osoba.prijmeni) |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name = 'Organizátor' |
||||
|
verbose_name_plural = 'Organizátoři' |
||||
|
# Řadí aktivní orgy na začátek, pod tím v pořadí od nejstarších neaktivní orgy. |
||||
|
# TODO: Chtěl bych spíš mít nejstarší orgy dole. |
||||
|
# TODO: Zohledňovat přezdívky? |
||||
|
# TODO: Sjednotit s tím, jak se řadí organizátoři v seznau orgů na webu |
||||
|
ordering = ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni'] |
@ -1,105 +0,0 @@ |
|||||
{% extends "base.html" %} |
|
||||
{% load staticfiles %} |
|
||||
|
|
||||
{% block script %} |
|
||||
<script src="{% static 'seminar/prihlaska.js' %}"></script> |
|
||||
{% endblock %} |
|
||||
|
|
||||
<!-- |
|
||||
|
|
||||
# pro přidání políčka do formuláře je potřeba |
|
||||
# - mít v modelu tu položku, kterou chci upravovat |
|
||||
# - přidat do views (prihlaskaView, resitelEditView) |
|
||||
# - přidat do forms |
|
||||
# - includovat do html |
|
||||
|
|
||||
--> |
|
||||
|
|
||||
{% block content %} |
|
||||
<h1> |
|
||||
{% block nadpis1a %}{% block nadpis1b %} |
|
||||
Změna osobních údajů |
|
||||
{% endblock %}{% endblock %} |
|
||||
</h1> |
|
||||
<form action="{% url 'seminar_resitel_edit' %}" method="post"> |
|
||||
{% csrf_token %} |
|
||||
{{form.non_field_errors}} |
|
||||
|
|
||||
<hr> |
|
||||
|
|
||||
<h4> |
|
||||
Přihlašovací údaje |
|
||||
</h4> |
|
||||
<table class="form"> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.username %} |
|
||||
</table> |
|
||||
|
|
||||
<hr> |
|
||||
|
|
||||
<h4> |
|
||||
Osobní údaje |
|
||||
</h4> |
|
||||
<table class="form"> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.jmeno %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.prijmeni %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.pohlavi_muz%} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.email %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.telefon %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.datum_narozeni %} |
|
||||
</table> |
|
||||
|
|
||||
<hr> |
|
||||
|
|
||||
<h4> |
|
||||
Bydliště |
|
||||
</h4> |
|
||||
<table class="form"> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.ulice %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.mesto %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.psc %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.stat %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.stat_text id="id_li_stat_text"%} |
|
||||
</table> |
|
||||
|
|
||||
<hr> |
|
||||
|
|
||||
<h4> |
|
||||
Škola |
|
||||
</h4> |
|
||||
<table class="form"> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.skola %} |
|
||||
<tr><td colspan="2" ><button id="id_skola_text_button" type="button">Škola není v seznamu</button></td></tr> |
|
||||
<tr><td id="id_li_skola_vypln" colspan="2">Vyplň prosím celý název a adresu školy.</td></tr> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.skola_nazev id="id_li_skola_nazev" %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.skola_adresa id="id_li_skola_adresa" %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.rok_maturity %} |
|
||||
</table> |
|
||||
|
|
||||
<hr> |
|
||||
|
|
||||
<h4> |
|
||||
Pošta |
|
||||
</h4> |
|
||||
<table class="form"> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.zasilat %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.zasilat_cislo_emailem %} |
|
||||
</table> |
|
||||
|
|
||||
<hr> |
|
||||
|
|
||||
<h4> |
|
||||
Zasílání propagačních materiálů |
|
||||
</h4> |
|
||||
<table class="form"> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.spam %} |
|
||||
</table> |
|
||||
|
|
||||
<hr> |
|
||||
|
|
||||
<input type="submit" value="Změnit"> |
|
||||
</form> |
|
||||
<script> |
|
||||
$("#id_stat").on("change",addrCountryChanged); |
|
||||
$("#id_skola_text_button").on("click",schoolNotInList); |
|
||||
</script> |
|
||||
{% endblock %} |
|
@ -1,123 +0,0 @@ |
|||||
{% extends "base.html" %} |
|
||||
{% load staticfiles %} |
|
||||
|
|
||||
{% block script %} |
|
||||
<script src="{% static 'seminar/prihlaska.js' %}"></script> |
|
||||
{% endblock %} |
|
||||
|
|
||||
<!-- |
|
||||
|
|
||||
# pro přidání políčka do formuláře je potřeba |
|
||||
# - mít v modelu tu položku, kterou chci upravovat |
|
||||
# - přidat do views (prihlaskaView, resitelEditView) |
|
||||
# - přidat do forms |
|
||||
# - includovat do html |
|
||||
|
|
||||
--> |
|
||||
|
|
||||
{% block content %} |
|
||||
<h1> |
|
||||
{% block nadpis1a %}{% block nadpis1b %} |
|
||||
Přihláška do semináře |
|
||||
{% endblock %}{% endblock %} |
|
||||
</h1> |
|
||||
|
|
||||
<p><b>Tučně</b> popsaná pole jsou povinná.</p> |
|
||||
|
|
||||
<form action="{% url 'seminar_prihlaska' %}" method="post"> |
|
||||
{% csrf_token %} |
|
||||
{{form.non_field_errors}} |
|
||||
|
|
||||
|
|
||||
<hr> |
|
||||
<h4> |
|
||||
Přihlašovací údaje |
|
||||
</h4> |
|
||||
<table class="form"> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.username %} |
|
||||
{# {% include "seminar/profil/prihlaska_field.html" with field=form.password %}#} |
|
||||
{# {% include "seminar/profil/prihlaska_field.html" with field=form.password_check %}#} |
|
||||
</table> |
|
||||
|
|
||||
<hr> |
|
||||
|
|
||||
<h4> |
|
||||
Osobní údaje |
|
||||
</h4> |
|
||||
<table class="form"> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.jmeno %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.prijmeni %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.pohlavi_muz%} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.email %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.telefon %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.datum_narozeni %} |
|
||||
</table> |
|
||||
|
|
||||
<hr> |
|
||||
|
|
||||
<h4> |
|
||||
Bydliště |
|
||||
</h4> |
|
||||
<table class="form"> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.ulice %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.mesto %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.psc %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.stat %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.stat_text id="id_li_stat_text"%} |
|
||||
</table> |
|
||||
|
|
||||
<hr> |
|
||||
|
|
||||
<h4> |
|
||||
Škola |
|
||||
</h4> |
|
||||
<table class="form"> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.skola %} |
|
||||
<tr><td colspan="2" ><button id="id_skola_text_button" type="button">Škola není v seznamu</button></td></tr> |
|
||||
<tr><td id="id_li_skola_vypln" colspan="2">Vyplň prosím celý název a adresu školy.</td></tr> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.skola_nazev id="id_li_skola_nazev" %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.skola_adresa id="id_li_skola_adresa" %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.rok_maturity %} |
|
||||
</table> |
|
||||
|
|
||||
<hr> |
|
||||
|
|
||||
<h4> |
|
||||
Pošta |
|
||||
</h4> |
|
||||
<table class="form"> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.zasilat %} |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.zasilat_cislo_emailem %} |
|
||||
</table> |
|
||||
<hr> |
|
||||
|
|
||||
<h4> |
|
||||
GDPR |
|
||||
</h4> |
|
||||
{% include "seminar/profil/gdpr.html" %} |
|
||||
<table class="form"> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.gdpr %} |
|
||||
</table> |
|
||||
|
|
||||
<hr> |
|
||||
|
|
||||
<h4> |
|
||||
Zasílání propagačních materiálů |
|
||||
</h4> |
|
||||
<table class="form"> |
|
||||
{% include "seminar/profil/prihlaska_field.html" with field=form.spam %} |
|
||||
</table> |
|
||||
|
|
||||
|
|
||||
|
|
||||
<hr> |
|
||||
|
|
||||
<input type="submit" value="Odeslat"> |
|
||||
</form> |
|
||||
<script> |
|
||||
$("#id_stat").on("change",addrCountryChanged); |
|
||||
$("#id_skola_text_button").on("click",schoolNotInList); |
|
||||
</script> |
|
||||
|
|
||||
|
|
||||
{% endblock %} |
|
Loading…
Reference in new issue