Skip to content
Snippets Groups Projects

Používání mo.web.fields

Merged Jiří Kalvoda requested to merge jk/fields into devel
All threads resolved!
1 file
+ 24
64
Compare changes
  • Side-by-side
  • Inline
+ 68
154
@@ -29,57 +29,25 @@ class UsersFilterForm(PagerForm):
search_email = wtforms.TextField("E-mail")
# participants
year = wtforms.IntegerField("Ročník")
school_code = wtforms.StringField("Škola")
year = mo_fields.OptionalInt("Ročník")
school = mo_fields.School()
# rounds->participations
round_year = wtforms.IntegerField("Ročník")
round_year = mo_fields.OptionalInt("Ročník")
round_category = wtforms.SelectField("Kategorie")
round_seq = wtforms.SelectField("Kolo")
contest_site_code = wtforms.StringField("Soutěžní oblast")
contest_site = mo_fields.Place("Soutěžní oblast")
participation_state = wtforms.SelectField('Účast', choices=[('*', '*')] + list(db.PartState.choices()))
submit = wtforms.SubmitField("Filtrovat")
# Výstupní hodnoty filtru, None při nepoužitém filtru, prázdná db hodnota při
# nepovedené filtraci (neexistující místo a podobně)
f_search_name: Optional[str] = None
f_search_email: Optional[str] = None
f_year: Optional[int] = None
f_school: Optional[db.Place] = None
f_round_category: Optional[str] = None
f_round_seq: Optional[int] = None
f_contest_site: Optional[db.Place] = None
f_participation_state: Optional[db.PartState] = None
def __init__(self, formdata, **kwargs):
super().__init__(formdata=formdata, **kwargs)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.round_category.choices = ['*'] + sorted(db.get_categories())
self.round_seq.choices = ['*'] + sorted(db.get_seqs())
def validate(self):
self.f_search_name = f"%{self.search_name.data}%" if self.search_name.data else None
self.f_search_email = f"%{self.search_email.data}%" if self.search_email.data else None
self.f_year = self.year.data
self.f_round_year = self.round_year.data
if self.school_code.data:
self.f_school = db.get_place_by_code(self.school_code.data)
if not self.f_school:
flash(f"Zadaná škola '{self.school_code.data}' neexistuje", "danger")
self.f_school = db.Place()
if self.contest_site_code.data:
self.f_contest_site = db.get_place_by_code(self.contest_site_code.data)
if not self.f_contest_site:
flash(f"Zadaná soutěžní oblast '{self.contest_site_code.data}' neexistuje", "danger")
self.f_contest_site = db.Place()
self.f_round_category = None if self.round_category.data == '*' else self.round_category.data
self.f_round_seq = None if self.round_seq.data == '*' else self.round_seq.data
self.f_participation_state = None if self.participation_state.data == '*' else self.participation_state.data
@app.route('/org/user/')
@app.route('/org/user/', methods=('GET', 'POST'))
def org_users():
sess = db.get_session()
rr = g.gatekeeper.rights_generic()
@@ -87,32 +55,33 @@ def org_users():
q = sess.query(db.User).filter_by(is_admin=False, is_org=False).options(
subqueryload(db.User.participants).joinedload(db.Participant.school_place)
)
filter = UsersFilterForm(request.args)
filter = UsersFilterForm(formdata=request.args)
if request.args:
filter.validate()
if filter.f_search_name:
if filter.search_name.data:
q = q.filter(or_(
db.User.first_name.ilike(filter.f_search_name),
db.User.last_name.ilike(filter.f_search_name)
db.User.first_name.ilike(f"%{filter.search_name.data}%"),
db.User.last_name .ilike(f"%{filter.search_name.data}%")
))
if filter.f_search_email:
q = q.filter(db.User.email.ilike(filter.f_search_email))
if filter.search_email.data:
q = q.filter(db.User.email.ilike(f"%{filter.search_email.data}%"))
if filter.f_year or filter.f_school:
if filter.year.data or filter.school.place:
participant_filter = sess.query(db.Participant.user_id)
if filter.f_year:
participant_filter = participant_filter.filter_by(year=filter.f_year)
if filter.f_school:
participant_filter = participant_filter.filter_by(school=filter.f_school.place_id)
if filter.year.data:
participant_filter = participant_filter.filter_by(year=filter.year.data)
if filter.school.place:
participant_filter = participant_filter.filter_by(school=filter.school.place.place_id)
q = q.filter(db.User.user_id.in_(participant_filter))
round_filter = sess.query(db.Round.round_id)
round_filter_apply = False
if filter.f_round_year:
round_filter = round_filter.filter_by(year=filter.f_round_year)
if filter.round_year.data:
round_filter = round_filter.filter_by(year=filter.round_year.data)
round_filter_apply = True
if filter.f_round_category:
round_filter = round_filter.filter_by(category=filter.f_round_category)
if filter.round_category.data and filter.round_category.data != "*":
round_filter = round_filter.filter_by(category=filter.round_category.data)
round_filter_apply = True
if filter.round_seq.data and filter.round_seq.data != "*":
round_filter = round_filter.filter_by(seq=filter.round_seq.data)
@@ -123,8 +92,8 @@ def org_users():
if round_filter_apply:
contest_filter = contest_filter.filter(db.Contest.round_id.in_(round_filter))
contest_filter_apply = True
if filter.f_contest_site:
contest_filter = contest_filter.filter_by(place_id=filter.f_contest_site.place_id)
if filter.contest_site.place:
contest_filter = contest_filter.filter_by(place_id=filter.contest_site.place.place_id)
contest_filter_apply = True
participation_filter = sess.query(db.Participation.user_id)
@@ -132,8 +101,8 @@ def org_users():
if contest_filter_apply:
participation_filter = participation_filter.filter(db.Participation.contest_id.in_(contest_filter))
participation_filter_apply = True
if filter.f_participation_state:
participation_filter = participation_filter.filter_by(state=filter.f_participation_state)
if filter.participation_state.data and filter.participation_state.data != '*':
participation_filter = participation_filter.filter_by(state=filter.participation_state.data)
participation_filter_apply = True
if participation_filter_apply:
@@ -150,18 +119,19 @@ def org_users():
can_add=rr.have_right(Right.add_users),
)
class OrgsFilterForm(PagerForm):
# user
search_name = wtforms.TextField("Jméno/příjmení", render_kw={'autofocus': True})
search_email = wtforms.TextField("E-mail")
search_role = wtforms.SelectMultipleField('Role', choices=db.RoleType.choices(), coerce=db.RoleType.coerce, validators=[validators.Optional()])
search_right_for_place_code = wtforms.StringField('Právo pro oblast', validators=[validators.Optional()])
search_in_place_code = wtforms.StringField('V oblasti', validators=[validators.Optional()])
search_right_for_place = mo_fields.Place('Právo pro oblast', validators=[validators.Optional()])
search_in_place = mo_fields.Place('V oblasti', validators=[validators.Optional()])
search_place_level = wtforms.SelectMultipleField("Úroveň oblasti", choices=[(i.level, i.name) for i in db.place_levels], validators=[validators.Optional()], coerce=int)
search_year = wtforms.StringField('Ročník', validators=[validators.Optional()])
search_year = mo_fields.IntList('Ročník', validators=[validators.Optional()])
search_category = wtforms.StringField("Kategorie", validators=[validators.Optional()])
search_seq = wtforms.StringField("Kolo", validators=[validators.Optional()])
search_seq = mo_fields.IntList("Kolo", validators=[validators.Optional()])
submit = wtforms.SubmitField("Filtrovat")
show_role_filter = wtforms.SubmitField("Zobrazit filtrování dle rolí")
@@ -169,54 +139,6 @@ class OrgsFilterForm(PagerForm):
is_role_filter = wtforms.HiddenField(default="") # "" -> skrýt. "yes" -> zobrazit
# Výstupní hodnoty filtru, None při nepoužitém filtru nebo špatné hodnotě (takové filtry ignorujeme)
f_search_name: Optional[str] = None
f_search_email: Optional[str] = None
f_search_role: Optional[List[db.RoleType]] = None
f_search_right_for_place: Optional[db.Place] = None
f_search_in_place: Optional[db.Place] = None
f_search_year: Optional[List[int]] = None
f_search_category: Optional[List[str]] = None
f_search_place_level: Optional[List[int]] = None
f_search_seq: Optional[List[int]] = None
def validate_search_name(self, field):
self.f_search_name = f"%{field.data}%"
def validate_search_email(self, field):
self.f_search_email = f"%{field.data}%"
def validate_search_role(self, field):
self.f_search_role = field.data
def validate_search_right_for_place_code(self, field):
self.f_search_right_for_place = db.get_place_by_code(field.data)
if self.f_search_right_for_place is None:
raise wtforms.ValidationError("Chybné označení oblasti")
def validate_search_in_place_code(self, field):
self.f_search_in_place = db.get_place_by_code(field.data)
if self.f_search_in_place is None:
raise wtforms.ValidationError("Chybné označení oblasti")
def validate_search_year(self, field):
try:
self.f_search_year = mo.util.parse_int_list(field.data)
except mo.CheckError as e:
raise wtforms.ValidationError(str(e))
def validate_search_category(self, field):
self.f_search_category = field.data.split(",")
def validate_search_place_level(self, field):
self.f_search_place_level = field.data
def validate_search_seq(self, field):
try:
self.f_search_seq = mo.util.parse_int_list(field.data)
except mo.CheckError as e:
raise wtforms.ValidationError(str(e))
def prepare_role_filter(self):
if self.show_role_filter.data:
self.is_role_filter.data = "yes"
@@ -227,8 +149,8 @@ class OrgsFilterForm(PagerForm):
else:
del self.hide_role_filter
del self.search_role
del self.search_right_for_place_code
del self.search_in_place_code
del self.search_right_for_place
del self.search_in_place
del self.search_place_level
del self.search_year
del self.search_category
@@ -242,34 +164,39 @@ def org_orgs():
q = sess.query(db.User).filter(or_(db.User.is_admin, db.User.is_org)).options(
subqueryload(db.User.roles).joinedload(db.UserRole.place)
)
filter = OrgsFilterForm()
filter.validate_on_submit()
filter = OrgsFilterForm(formdata=request.args)
if request.args:
filter.validate()
filter.prepare_role_filter()
if filter.f_search_name:
if filter.search_name.data:
q = q.filter(or_(
db.User.first_name.ilike(filter.f_search_name),
db.User.last_name.ilike(filter.f_search_name)
db.User.first_name.ilike(f"%{filter.search_name.data}%"),
db.User.last_name .ilike(f"%{filter.search_name.data}%")
))
if filter.search_email.data:
q = q.filter(db.User.email.ilike(f"%{filter.search_email.data}%"))
def query_filter_role(qr: flask_sqlalchemy.BaseQuery) -> flask_sqlalchemy.BaseQuery:
if filter.f_search_role is not None:
qr = qr.filter(db.UserRole.role.in_(filter.f_search_role))
if filter.f_search_category is not None:
qr = qr.filter(or_(db.UserRole.category.in_(filter.f_search_category), db.UserRole.category == None))
if filter.f_search_seq is not None:
qr = qr.filter(or_(db.UserRole.seq.in_(filter.f_search_seq), db.UserRole.seq == None))
if filter.f_search_year is not None:
qr = qr.filter(or_(db.UserRole.year.in_(filter.f_search_year), db.UserRole.year == None))
if filter.f_search_in_place is not None:
qr = qr.filter(db.UserRole.place_id.in_(db.place_descendant_cte(filter.f_search_in_place)))
if filter.f_search_right_for_place is not None:
qr = qr.filter(db.UserRole.place_id.in_([x.place_id for x in db.get_place_parents(filter.f_search_right_for_place)]))
if filter.search_role.data:
qr = qr.filter(db.UserRole.role.in_(filter.search_role.data))
if filter.search_category.data:
qr = qr.filter(or_(db.UserRole.category.in_(filter.search_category.data.split(",")), db.UserRole.category == None))
if filter.search_seq.list:
qr = qr.filter(or_(db.UserRole.seq.in_(filter.search_seq.list), db.UserRole.seq == None))
if filter.search_year.list:
qr = qr.filter(or_(db.UserRole.year.in_(filter.search_year.list), db.UserRole.year == None))
pass
if filter.search_in_place.place is not None:
qr = qr.filter(db.UserRole.place_id.in_(db.place_descendant_cte(filter.search_in_place.place)))
if filter.search_right_for_place.place is not None:
qr = qr.filter(db.UserRole.place_id.in_([x.place_id for x in db.get_place_parents(filter.search_right_for_place.place)]))
# Po n>3 hodinách v mo.db jsem dospěl k závěru, že to hezčeji neumím (neumím vyrobit place_parents_cte)
if filter.f_search_place_level is not None:
if filter.search_place_level.data:
qr = qr.filter(db.UserRole.place_id.in_(
sess.query(db.Place.place_id).filter(db.Place.level.in_(filter.f_search_place_level))
sess.query(db.Place.place_id).filter(db.Place.level.in_(filter.search_place_level.data))
))
print(qr)
return qr
if filter.is_role_filter.data:
@@ -300,7 +227,7 @@ def org_orgs():
class FormAddRole(FlaskForm):
role = wtforms.SelectField('Role', choices=db.RoleType.choices(), coerce=db.RoleType.coerce, render_kw={'autofocus': True})
place_code = wtforms.StringField('Oblast')
place = mo_fields.Place()
year = wtforms.IntegerField('Ročník', validators=[validators.Optional()])
category = wtforms.StringField("Kategorie", validators=[validators.Length(max=2)], filters=[lambda x: x or None])
seq = wtforms.IntegerField("Kolo", validators=[validators.Optional()])
@@ -360,14 +287,7 @@ def org_org(id: int):
new_role.assigned_by = g.user.user_id
ok = True
place_code = form_add_role.place_code.data
if place_code:
place = db.get_place_by_code(place_code)
if not place:
role_errors.append("Nepovedlo se nalézt místo podle kódu")
ok = False
else:
new_role.place = place
new_role.place = form_add_role.place.place
if not g.gatekeeper.can_set_role(new_role):
role_errors.append(f'Roli "{new_role}" nelze přidělit, není podmnožinou žádné vaší role')
@@ -454,20 +374,14 @@ def org_user(id: int):
class UserEditForm(FlaskForm):
first_name = wtforms.StringField("Jméno", validators=[Required()], render_kw={'autofocus': True})
last_name = wtforms.StringField("Příjmení", validators=[Required()])
email = wtforms.StringField("E-mail", validators=[Required()])
first_name = mo_fields.FirstName(validators=[Required()], render_kw={'autofocus': True})
last_name = mo_fields.LastName(validators=[Required()])
email = mo_fields.Email(validators=[Required()])
note = wtforms.TextAreaField("Poznámka")
is_test = wtforms.BooleanField("Testovací účet")
allow_duplicate_name = wtforms.BooleanField("Přidat účet s duplicitním jménem")
submit = wtforms.SubmitField("Uložit")
def validate_email(form, field):
try:
field.data = mo.users.normalize_email(field.data)
except mo.CheckError as e:
raise wtforms.ValidationError(str(e))
@app.route('/org/org/<int:id>/edit', methods=("GET", "POST"), endpoint="org_org_edit")
@app.route('/org/user/<int:id>/edit', methods=("GET", "POST"))
Loading