1
0
forked from ScoDoc/ScoDoc

petit refactoring (photos)

This commit is contained in:
Emmanuel Viennet 2021-12-20 22:53:09 +01:00
parent 8532ab5134
commit f1c43a5bb8
5 changed files with 56 additions and 44 deletions

View File

@ -9,7 +9,6 @@ from app import models
from app.models import APO_CODE_STR_LEN
from app.models import SHORT_STR_LEN
from app.models import CODE_STR_LEN
from app.scodoc import sco_photos
class Identite(db.Model):
@ -71,9 +70,11 @@ class Identite(db.Model):
"le mail associé à la première adrese de l'étudiant, ou None"
return self.adresses[0].email or None if self.adresses.count() > 0 else None
def to_dict_bul(self):
def to_dict_bul(self, include_photo=True):
"""Infos exportées dans les bulletins"""
return {
from app.scodoc import sco_photos
d = {
"civilite": self.civilite,
"code_ine": self.code_nip,
"code_nip": self.code_ine,
@ -84,9 +85,11 @@ class Identite(db.Model):
"emailperso": self.get_first_email("emailperso"),
"etudid": self.id,
"nom": self.nom_disp(),
"photo_url": sco_photos.get_etud_photo_url(self.id),
"prenom": self.prenom,
}
if include_photo:
d["photo_url"] = (sco_photos.get_etud_photo_url(self.id),)
return d
def inscription_courante(self):
"""La première inscription à un formsemestre _actuellement_ en cours.

View File

@ -42,9 +42,6 @@ Les images sont servies par ScoDoc, via la méthode getphotofile?etudid=xxx
- support for legacy ZODB removed in v1909.
"""
from flask.helpers import make_response, url_for
from app.scodoc.sco_exceptions import ScoGenError
import datetime
import glob
import io
@ -52,24 +49,26 @@ import os
import random
import requests
import time
import traceback
import PIL
from PIL import Image as PILImage
from flask import request, g
from flask.helpers import make_response, url_for
from config import Config
from app import log
from app import db
from app.models import Identite
from app.scodoc import sco_etud
from app.scodoc import sco_portal_apogee
from app.scodoc import sco_preferences
from app import log
from app.scodoc.sco_exceptions import ScoGenError
from app.scodoc.scolog import logdb
import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu
from config import Config
# Full paths on server's filesystem. Something like "/opt/scodoc/var/scodoc/photos"
# Full paths on server's filesystem. Something like "/opt/scodoc-data/photos"
PHOTO_DIR = os.path.join(Config.SCODOC_VAR_DIR, "photos")
ICONS_DIR = os.path.join(Config.SCODOC_DIR, "app", "static", "icons")
UNKNOWN_IMAGE_PATH = os.path.join(ICONS_DIR, "unknown.jpg")
@ -97,14 +96,15 @@ def get_etud_photo_url(etudid, size="small"):
)
def etud_photo_url(etud, size="small", fast=False):
def etud_photo_url(etud: dict, size="small", fast=False) -> str:
"""url to the image of the student, in "small" size or "orig" size.
If ScoDoc doesn't have an image and a portal is configured, link to it.
"""
photo_url = get_etud_photo_url(etud["etudid"], size=size)
if fast:
return photo_url
path = photo_pathname(etud, size=size)
path = photo_pathname(etud["photo_filename"], size=size)
if not path:
# Portail ?
ext_url = photo_portal_url(etud)
@ -131,8 +131,8 @@ def get_photo_image(etudid=None, size="small"):
if not etudid:
filename = UNKNOWN_IMAGE_PATH
else:
etud = sco_etud.get_etud_info(filled=True, etudid=etudid)[0]
filename = photo_pathname(etud, size=size)
etud = Identite.query.get_or_404(etudid)
filename = photo_pathname(etud.photo_filename, size=size)
if not filename:
filename = UNKNOWN_IMAGE_PATH
return _http_jpeg_file(filename)
@ -171,8 +171,8 @@ def _http_jpeg_file(filename):
return response
def etud_photo_is_local(etud, size="small"):
return photo_pathname(etud, size=size)
def etud_photo_is_local(etud: dict, size="small"):
return photo_pathname(etud["photo_filename"], size=size)
def etud_photo_html(etud=None, etudid=None, title=None, size="small"):
@ -215,9 +215,12 @@ def etud_photo_orig_html(etud=None, etudid=None, title=None):
return etud_photo_html(etud=etud, etudid=etudid, title=title, size="orig")
def photo_pathname(etud, size="orig"):
"""Returns full path of image file if etud has a photo (in the filesystem), or False.
def photo_pathname(photo_filename: str, size="orig"):
"""Returns full path of image file if etud has a photo (in the filesystem),
or False.
Do not distinguish the cases: no photo, or file missing.
Argument: photo_filename (Identite attribute)
Resultat: False or str
"""
if size == "small":
version = H90
@ -225,9 +228,9 @@ def photo_pathname(etud, size="orig"):
version = ""
else:
raise ValueError("invalid size parameter for photo")
if not etud["photo_filename"]:
if not photo_filename:
return False
path = os.path.join(PHOTO_DIR, etud["photo_filename"]) + version + IMAGE_EXT
path = os.path.join(PHOTO_DIR, photo_filename) + version + IMAGE_EXT
if os.path.exists(path):
return path
else:
@ -264,15 +267,14 @@ def store_photo(etud, data):
return 1, "ok"
def suppress_photo(etud):
def suppress_photo(etud: Identite) -> None:
"""Suppress a photo"""
log("suppress_photo etudid=%s" % etud["etudid"])
rel_path = photo_pathname(etud)
log("suppress_photo etudid=%s" % etud.id)
rel_path = photo_pathname(etud.photo_filename)
# 1- remove ref. from database
etud["photo_filename"] = None
cnx = ndb.GetDBConnexion()
sco_etud.identite_edit_nocheck(cnx, etud)
cnx.commit()
etud.photo_filename = None
db.session.add(etud)
# 2- erase images files
if rel_path:
# remove extension and glob
@ -281,8 +283,10 @@ def suppress_photo(etud):
for filename in filenames:
log("removing file %s" % filename)
os.remove(filename)
db.session.commit()
# 3- log
logdb(cnx, method="changePhoto", msg="suppression", etudid=etud["etudid"])
cnx = ndb.GetDBConnexion()
logdb(cnx, method="changePhoto", msg="suppression", etudid=etud.id)
# ---------------------------------------------------------------------------
@ -373,6 +377,9 @@ def copy_portal_photo_to_fs(etud):
log("copy_portal_photo_to_fs: failure (exception in store_photo)!")
if status == 1:
log("copy_portal_photo_to_fs: copied %s" % url)
return photo_pathname(etud), "%s: photo chargée" % etud["nomprenom"]
return (
photo_pathname(etud["photo_filename"]),
f"{etud['nomprenom']}: photo chargée",
)
else:
return None, "%s: <b>%s</b>" % (etud["nomprenom"], diag)

View File

@ -183,10 +183,11 @@ def trombino_html(groups_infos):
def check_local_photos_availability(groups_infos, format=""):
"""Verifie que toutes les photos (des gropupes indiqués) sont copiées localement
dans ScoDoc (seules les photos dont nous disposons localement peuvent être exportées
en pdf ou en zip).
Si toutes ne sont pas dispo, retourne un dialogue d'avertissement pour l'utilisateur.
"""Vérifie que toutes les photos (des groupes indiqués) sont copiées
localement dans ScoDoc (seules les photos dont nous disposons localement
peuvent être exportées en pdf ou en zip).
Si toutes ne sont pas dispo, retourne un dialogue d'avertissement
pour l'utilisateur.
"""
nb_missing = 0
for t in groups_infos.members:
@ -221,7 +222,7 @@ def _trombino_zip(groups_infos):
# assume we have the photos (or the user acknowledged the fact)
# Archive originals (not reduced) images, in JPEG
for t in groups_infos.members:
im_path = sco_photos.photo_pathname(t, size="orig")
im_path = sco_photos.photo_pathname(t["photo_filename"], size="orig")
if not im_path:
continue
img = open(im_path, "rb").read()
@ -292,9 +293,9 @@ def trombino_copy_photos(group_ids=[], dialog_confirmed=False):
def _get_etud_platypus_image(t, image_width=2 * cm):
"""Returns aplatypus object for the photo of student t"""
"""Returns a platypus object for the photo of student t"""
try:
path = sco_photos.photo_pathname(t, size="small")
path = sco_photos.photo_pathname(t["photo_filename"], size="small")
if not path:
# log('> unknown')
path = sco_photos.UNKNOWN_IMAGE_PATH

View File

@ -134,7 +134,7 @@ def get_etud_dept():
last_etud = None
last_date = None
for etud in etuds:
inscriptions = FormSemestreInscription.query.filter_by(etudid=etud.id).all()
inscriptions = FormsemestreInscription.query.filter_by(etudid=etud.id).all()
for ins in inscriptions:
date_fin = FormSemestre.query.get(ins.formsemestre_id).date_fin
if (last_date is None) or date_fin > last_date:

View File

@ -49,6 +49,7 @@ from app.decorators import (
admin_required,
login_required,
)
from app.models.etudiants import Identite
from app.views import scolar_bp as bp
@ -944,21 +945,21 @@ def formChangePhoto(etudid=None):
@scodoc7func
def formSuppressPhoto(etudid=None, dialog_confirmed=False):
"""Formulaire suppression photo étudiant"""
etud = sco_etud.get_etud_info(filled=True)[0]
etud = Identite.query.get_or_404(etudid)
if not dialog_confirmed:
return scu.confirm_dialog(
"<p>Confirmer la suppression de la photo de %(nomprenom)s ?</p>" % etud,
f"<p>Confirmer la suppression de la photo de {etud.nom_disp()} ?</p>",
dest_url="",
cancel_url=url_for(
"scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid
"scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etud.id
),
parameters={"etudid": etudid},
parameters={"etudid": etud.id},
)
sco_photos.suppress_photo(etud)
return flask.redirect(
url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid)
url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etud.id)
)