Skip to content
Snippets Groups Projects
Select Git revision
  • 0e78c590f981f3cea39a2aa3d6d00a91266cc373
  • devel default
  • master
  • fo
  • jirka/typing
  • fo-base
  • mj/submit-images
  • jk/issue-96
  • jk/issue-196
  • honza/add-contestant
  • honza/mr7
  • honza/mrf
  • honza/mrd
  • honza/mra
  • honza/mr6
  • honza/submit-images
  • honza/kolo-vs-soutez
  • jh-stress-test-wip
  • shorten-schools
19 results

fields.py

Blame
  • Jiri Kalvoda's avatar
    Jiří Kalvoda authored
    de119c89
    History
    fields.py 7.25 KiB
    import decimal
    from typing import Optional
    import wtforms
    from wtforms.fields.html5 import EmailField
    from wtforms.widgets.html5 import NumberInput
    
    import mo
    import mo.users
    import mo.db as db
    
    
    class OptionalInt(wtforms.IntegerField):
        widget = NumberInput()
    
        def process_formdata(self, valuelist):
            self.data = None
            if valuelist:
                if valuelist[0]:
                    try:
                        self.data = int(valuelist[0])
                    except ValueError:
                        raise wtforms.ValidationError('Nejedná se o číslo.')
    
    
    class Decimal(wtforms.DecimalField):
        """Upravený DecimalField, který formátuje číslo podle jeho skutečného počtu
        desetinných míst a zadané `places` používá jen jako maximální počet desetinných míst."""
    
        def _value(self):
            if self.data is not None:
                # Spočítání počtu desetinných míst, zbytek necháme na původní implementaci
                max_places = self.places
                self.places = 0
                d = decimal.Decimal(1)
    
                while self.data % d != 0 and self.places < max_places:
                    self.places += 1
                    d /= 10
    
            return super(Decimal, self)._value()
    
    
    class IntList(wtforms.StringField):
        list = None
    
        def __init__(self, label="", validators=None, **kwargs):
            super().__init__(label, validators, **kwargs)
    
        def pre_validate(field, form):
            field.list = None
            if field.data:
                try:
                    field.list = mo.util.parse_int_list(field.data)
                except mo.CheckError as e:
                    raise wtforms.ValidationError(str(e))
    
    class Points(Decimal):
        def __init__(self, label="Body", validators=None, **kwargs):
            super().__init__(label, validators, **kwargs)
    
    
    
    class Email(EmailField):
        def __init__(self, label="E-mail", validators=None, **kwargs):
            super().__init__(label, validators, **kwargs)
    
        def pre_validate(field, form):
            if field.data:
                try:
                    field.data = mo.users.normalize_email(field.data)
                except mo.CheckError as e:
                    raise wtforms.ValidationError(str(e))
    
    
    class Grade(wtforms.StringField):
        """Pro validaci hledá ve formuláři form.school a podle ní rozlišuje SŠ a ZŠ """
        default_description = "Pro základní školy je to číslo od 1 do 9, pro <var>k</var>-tý ročník <var>r</var>-leté střední školy má formát <var>k</var>/<var>r</var>."
        validate_grade = True
    
        def __init__(self, label="Ročník", validators=None, description=default_description, **kwargs):
            super().__init__(label, validators, description=description, **kwargs)
    
        def pre_validate(field, form):
            if field.data:
                if field.validate_grade:
                    school_place = form.school.get_place()
                    if school_place is not None:
                        try:
                            field.data = mo.users.normalize_grade(field.data, school_place.school)
                        except mo.CheckError as e:
                            raise wtforms.ValidationError(str(e))
    
    
    class BirthYear(OptionalInt):
        def __init__(self, label="Rok narození", validators=None, **kwargs):
            super().__init__(label, validators, **kwargs)
    
        def pre_validate(field, form):
            if field.data is not None:
                r: int = field.data
                try:
                    mo.users.validate_born_year(r)
                except mo.CheckError as e:
                    raise wtforms.ValidationError(str(e))
    
    
    class Name(wtforms.StringField):
        def pre_validate(field, form):
            # XXX: Tato kontrola úmyslně není striktní, aby prošla i jména jako 'de Beer'
            if field.data:
                if field.data == field.data.lower():
                    raise wtforms.ValidationError('Ve jméně nejsou velká písmena.')
                if field.data == field.data.upper():
                    raise wtforms.ValidationError('Ve jméně nejsou malá písmena.')
    
    
    class FirstName(Name):
        def __init__(self, label="Jméno", validators=None, **kwargs):
            super().__init__(label, validators, **kwargs)
    
    
    class LastName(Name):
        def __init__(self, label="Příjmení", validators=None, **kwargs):
            super().__init__(label, validators, **kwargs)
    
    
    class Place(wtforms.StringField):
        def __init__(self, label="Místo", validators=None, **kwargs):
            super().__init__(label, validators, **kwargs)
            self.render_kw = {"placeholder": "Kód"}
    
        place_loaded: bool = False
        place: Optional[db.Place] = None
        place_error: str = ""
    
        def load_place(field) -> None:
            field.place = None
            field.place_error = ""
            if field.data:
                field.place = db.get_place_by_code(field.data)
                if field.place is None:
                    field.place_error = "Zadané místo nenalezeno."
    
        def get_place(field) -> Optional[db.Place]:
            """ Kešuje výsledek v field.place"""
            if not field.place_loaded:
                field.place_loaded = True
                field.load_place()
            return field.place
    
        def pre_validate(field, form):
            if field.get_place() is None and field.place_error:
                raise wtforms.ValidationError(field.place_error)
    
        def get_place_id(field) -> int:
            p = field.get_place()
            if p is None:
                return 0
            return p.place_id
    
        def populate_obj(field, obj, name):
            setattr(obj, name, field.get_place_id())
    
        def process_data(field, obj: Optional[int]):
            if obj is not None:
                field.data = db.get_place_by_id(obj).get_code()
            else:
                field.data = ""
    
    
    class School(Place):
        def __init__(self, label="Škola", validators=None, **kwargs):
            super().__init__(label, validators, **kwargs)
    
        def load_place(field) -> None:
            field.place = None
            field.place_error = ""
            if field.data:
                try:
                    field.place = mo.users.validate_and_find_school(field.data)
                except mo.CheckError as e:
                    field.place_error = str(e)
    
    
    class NewPassword(wtforms.PasswordField):
        def __init__(self, label="Nové heslo", validators=None, **kwargs):
            super().__init__(label, validators, **kwargs)
    
        def pre_validate(field, form):
            if field.data:
                if not mo.users.validate_password(field.data):
                    raise wtforms.ValidationError(mo.users.password_help)
    
    
    class RepeatPassword(wtforms.PasswordField):
        """Pro validaci hledá ve formuláři form.new_passwd a s ním porovnává."""
    
        def __init__(self, label="Zopakujte heslo", validators=None, **kwargs):
            super().__init__(label, validators, **kwargs)
    
        def pre_validate(field, form):
            if field.data != form.new_passwd.data:
                raise wtforms.ValidationError('Hesla se neshodují.')
    
    
    class DateTime(wtforms.DateTimeField):
        def __init__(self, label, format='%Y-%m-%d %H:%M', description='Ve formátu 2000-01-01 12:34', **kwargs):
            super().__init__(label, format=format, description=description, **kwargs)
    
        def process_data(self, valuelist):
            super().process_data(valuelist)
            if self.data is not None:
                self.data = self.data.astimezone()
    
        def process_formdata(self, valuelist):
            super().process_formdata(valuelist)
            if self.data is not None:
                self.data = self.data.astimezone()