Fixes - fiche utilisateur ok

This commit is contained in:
Emmanuel Viennet 2021-08-10 17:12:10 +02:00
parent 77fc1c7de2
commit 4a43e96fe9
24 changed files with 148 additions and 95 deletions

View File

@ -151,5 +151,5 @@ class EtudAnnotation(db.Model):
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
etudid = db.Column(db.Integer) # sans contrainte pour garder logs après suppression
authenticated_user = db.Column(db.Text)
author = db.Column(db.Text) # le pseudo (user_name)
comment = db.Column(db.Text)

View File

@ -114,7 +114,7 @@ class NotesAppreciations(db.Model):
db.Integer,
db.ForeignKey("notes_formsemestre.id"),
)
author = db.Column(db.Text) # login, sans contrainte
author = db.Column(db.Text) # le pseudo (user_name), sans contrainte
comment = db.Column(db.Text) # texte libre

View File

@ -301,6 +301,8 @@ class EditableTable(object):
vals = dictfilter(args, self.dbfields, self.filter_nulls)
if self.id_name in vals:
del vals[self.id_name]
if "id" in vals:
del vals["id"]
if self.html_quote:
quote_dict(vals) # quote all HTML markup
# format value

View File

@ -393,7 +393,7 @@ def get_avis_poursuite_par_etudiant(
result: [ chaine unicode, chaine unicode ]
"""
if pe_tools.PE_DEBUG:
pe_tools.pe_print(jury.syntheseJury[etudid]["nom"] + " " + etudid)
pe_tools.pe_print(jury.syntheseJury[etudid]["nom"] + " " + str(etudid))
civilite_str = jury.syntheseJury[etudid]["civilite_str"]
nom = jury.syntheseJury[etudid]["nom"].replace(" ", "-")
@ -405,7 +405,7 @@ def get_avis_poursuite_par_etudiant(
+ "_"
+ pe_tools.remove_accents(prenom)
+ "_"
+ etudid
+ str(etudid)
)
if pe_tools.PE_DEBUG:
pe_tools.pe_print("fichier latex =" + nom_fichier, type(nom_fichier))

View File

@ -423,7 +423,7 @@ class JuryPE(object):
fid = sesFormsemestre_idValidants[i]
self.PARCOURSINFO_DICT[etudid][nom_sem] = fid # ['formsemestre_id']
if fid != None and pe_tools.PE_DEBUG and pe_tools.PE_DEBUG >= 2:
pe_tools.pe_print(nom_sem + "=" + fid, end="")
pe_tools.pe_print(nom_sem + "=" + str(fid), end="")
# self.get_moyennesEtClassements_par_semestre_d_un_etudiant( etudid, fid )
# Quelles sont ses années validantes ('1A', '2A') et ses parcours (3S, 4S) validants ?
@ -1170,7 +1170,7 @@ class JuryPE(object):
nom_sem
] # le formsemestre_id du semestre taggué de l'étudiant
semtag = self.semTagDict[semtagid]
chaine += "Semestre " + nom_sem + semtagid + "\n"
chaine += "Semestre " + nom_sem + str(semtagid) + "\n"
# le détail du calcul tag par tag
# chaine += "Détail du calcul du tag\n"
# chaine += "-----------------------\n"

View File

@ -360,7 +360,12 @@ class SemestreTag(pe_tagtable.TableTag):
lesEtuds = []
for etudid in lesEtuds:
descr = "%15s" % self.nt.get_nom_short(etudid)[:15] + delim + etudid + delim
descr = (
"%15s" % self.nt.get_nom_short(etudid)[:15]
+ delim
+ str(etudid)
+ delim
)
if tag in taglist:
for modimpl_id in self.tagdict[tag]:
(note, coeff) = self.get_noteEtCoeff_modimpl(modimpl_id, etudid)
@ -433,7 +438,7 @@ class SemestreTag(pe_tagtable.TableTag):
+ "*"
+ str(mod["ponderation"])
+ ") "
+ modid
+ str(modid)
+ ", "
)
chaine += "\n"

View File

@ -101,7 +101,7 @@ class BaseArchiver(object):
if not os.path.isdir(dept_dir):
log("creating directory %s" % dept_dir)
os.mkdir(dept_dir)
obj_dir = os.path.join(dept_dir, oid)
obj_dir = os.path.join(dept_dir, str(oid))
if not os.path.isdir(obj_dir):
log("creating directory %s" % obj_dir)
os.mkdir(obj_dir)
@ -144,7 +144,7 @@ class BaseArchiver(object):
dt = [int(x) for x in os.path.split(archive_id)[1].split("-")]
return datetime.datetime(*dt)
def list_archive(self, archive_id):
def list_archive(self, archive_id: str) -> str:
"""Return list of filenames (without path) in archive"""
try:
scu.GSL.acquire()
@ -152,9 +152,7 @@ class BaseArchiver(object):
finally:
scu.GSL.release()
files.sort()
return [
f.encode(scu.SCO_ENCODING) for f in files if f and f[0] != "_"
] # sco8 XXX
return [f for f in files if f and f[0] != "_"]
def get_archive_name(self, archive_id):
"""name identifying archive, to be used in web URLs"""
@ -183,7 +181,7 @@ class BaseArchiver(object):
"""Return description of archive"""
return open(os.path.join(archive_id, "_description.txt")).read()
def create_obj_archive(self, context, oid, description):
def create_obj_archive(self, context, oid: int, description: str):
"""Creates a new archive for this object and returns its id."""
archive_id = (
self.get_obj_dir(context, oid)
@ -196,10 +194,10 @@ class BaseArchiver(object):
os.mkdir(archive_id) # if exists, raises an OSError
finally:
scu.GSL.release()
self.store(archive_id, "_description.txt", description)
self.store(archive_id, "_description.txt", description.encode("utf-8"))
return archive_id
def store(self, archive_id, filename, data):
def store(self, archive_id: str, filename: str, data: bytes):
"""Store data in archive, under given filename.
Filename may be modified (sanitized): return used filename
The file is created or replaced.
@ -209,21 +207,21 @@ class BaseArchiver(object):
try:
scu.GSL.acquire()
fname = os.path.join(archive_id, filename)
f = open(fname, "w")
f = open(fname, "wb")
f.write(data)
f.close()
finally:
scu.GSL.release()
return filename
def get(self, archive_id, filename):
def get(self, archive_id: str, filename: str):
"""Retreive data"""
if not scu.is_valid_filename(filename):
log('Archiver.get: invalid filename "%s"' % filename)
raise ValueError("invalid filename")
fname = os.path.join(archive_id, filename)
log("reading archive file %s" % fname)
return open(fname).read()
return open(fname, "rb").read()
def get_archived_file(self, context, REQUEST, oid, archive_name, filename):
"""Recupere donnees du fichier indiqué et envoie au client"""
@ -242,8 +240,8 @@ class BaseArchiver(object):
return scu.sendCSVFile(REQUEST, data, filename)
elif ext == ".pdf":
return scu.sendPDFFile(REQUEST, data, filename)
return data # should set mimetype...
REQUEST.RESPONSE.setHeader("content-type", "application/octet-stream")
return data # should set mimetype for known files like images
class SemsArchiver(BaseArchiver):

View File

@ -169,9 +169,9 @@ def etud_upload_file_form(context, REQUEST, etudid):
url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid)
)
else:
data = tf[2]["datafile"][0].read()
data = tf[2]["datafile"].read()
descr = tf[2]["description"]
filename = tf[2]["datafile"][0].filename
filename = tf[2]["datafile"].filename
_store_etud_file_to_new_archive(
context, REQUEST, etudid, data, filename, description=descr
)

View File

@ -28,7 +28,7 @@
"""
Rapport (table) avec dernier semestre fréquenté et débouché de chaque étudiant
"""
import http
from flask import url_for, g
import app.scodoc.sco_utils as scu
@ -372,3 +372,4 @@ def itemsuivi_tag_set(context, itemsuivi_id="", taglist=[], REQUEST=None):
for tagname in to_del:
t = ItemSuiviTag(context, tagname)
t.remove_tag_from_object(itemsuivi_id)
return "", http.HTTPStatus.NO_CONTENT

View File

@ -307,9 +307,13 @@ def check_nom_prenom(cnx, nom="", prenom="", etudid=None):
return False, 0
# Now count homonyms:
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
req = "select etudid from identite where lower(nom) ~ %(nom)s and lower(prenom) ~ %(prenom)s"
req = """SELECT id
FROM identite
WHERE lower(nom) ~ %(nom)s
and lower(prenom) ~ %(prenom)s
"""
if etudid:
req += " and etudid <> %(etudid)s"
req += " and id <> %(etudid)s"
cursor.execute(req, {"nom": nom, "prenom": prenom, "etudid": etudid})
res = cursor.dictfetchall()
return True, len(res)
@ -559,6 +563,7 @@ _admissionEditor = ndb.EditableTable(
"annee_bac": pivot_year,
"classement": ndb.int_null_is_null,
"apb_classement_gr": ndb.int_null_is_null,
"boursier_prec": bool,
},
output_formators={"type_admission": lambda x: x or scu.TYPE_ADMISSION_DEFAULT},
convert_null_outputs_to_empty=True,
@ -747,8 +752,7 @@ _etud_annotationsEditor = ndb.EditableTable(
"etudid",
"author",
"comment",
"zope_authenticated_user",
"zope_remote_addr",
"author",
),
sortkey="date desc",
convert_null_outputs_to_empty=True,
@ -786,8 +790,7 @@ _appreciationsEditor = ndb.EditableTable(
"formsemestre_id",
"author",
"comment",
"zope_authenticated_user",
"zope_remote_addr",
"author",
),
sortkey="date desc",
convert_null_outputs_to_empty=True,

View File

@ -137,7 +137,7 @@ def formation_export(
)
def formation_import_xml(context, doc, import_tags=True):
def formation_import_xml(context, doc: str, import_tags=True):
"""Create a formation from XML representation
(format dumped by formation_export( format='xml' ))
XML may contain object (UE, modules) ids: this function returns two

View File

@ -1319,10 +1319,14 @@ def formsemestre_delete(context, formsemestre_id, REQUEST=None):
return "\n".join(H) + html_sco_header.sco_footer()
elif tf[0] == -1: # cancel
return flask.redirect(
scu.NotesURL() + "/formsemestre_status?formsemestre_id=" + formsemestre_id
scu.NotesURL()
+ "/formsemestre_status?formsemestre_id="
+ str(formsemestre_id)
)
else:
return flask.redirect("formsemestre_delete2?formsemestre_id=" + formsemestre_id)
return flask.redirect(
"formsemestre_delete2?formsemestre_id=" + str(formsemestre_id)
)
def formsemestre_delete2(

View File

@ -181,7 +181,7 @@ def formsemestre_validation_etud_form(
if not desturl:
desturl = (
"formsemestre_recapcomplet?modejury=1&hidemodules=1&hidebac=1&pref_override=0&formsemestre_id="
+ formsemestre_id
+ str(formsemestre_id)
)
if sortcol:
desturl += (
@ -427,7 +427,7 @@ def _redirect_valid_choice(
# flask.redirect( 'formsemestre_validation_etud_form?formsemestre_id=%s&etudid=%s&check=1&desturl=%s' % (formsemestre_id, etudid, desturl) )
# else:
# if not desturl:
# desturl = 'formsemestre_recapcomplet?modejury=1&hidemodules=1&formsemestre_id=' + formsemestre_id
# desturl = 'formsemestre_recapcomplet?modejury=1&hidemodules=1&formsemestre_id=' + str(formsemestre_id)
# flask.redirect(desturl)
@ -1082,7 +1082,7 @@ def formsemestre_validate_previous_ue(context, formsemestre_id, etudid, REQUEST=
return "\n".join(H) + tf[1] + X + warn + html_sco_header.sco_footer()
elif tf[0] == -1:
return flask.redirect(
scu.NotesURL() + "/formsemestre_status?formsemestre_id=" + formsemestre_id
scu.NotesURL() + "/formsemestre_status?formsemestre_id=" + str(formsemestre_id)
)
else:
if tf[2]["semestre_id"]:

View File

@ -1035,7 +1035,9 @@ def partition_delete(
# redirect to partition edit page:
if redirect:
return flask.redirect("editPartitionForm?formsemestre_id=" + formsemestre_id)
return flask.redirect(
"editPartitionForm?formsemestre_id=" + str(formsemestre_id)
)
def partition_move(context, partition_id, after=0, REQUEST=None, redirect=1):
@ -1068,7 +1070,9 @@ def partition_move(context, partition_id, after=0, REQUEST=None, redirect=1):
# redirect to partition edit page:
if redirect:
return flask.redirect("editPartitionForm?formsemestre_id=" + formsemestre_id)
return flask.redirect(
"editPartitionForm?formsemestre_id=" + str(formsemestre_id)
)
def partition_rename(context, partition_id, REQUEST=None):
@ -1105,7 +1109,9 @@ def partition_rename(context, partition_id, REQUEST=None):
+ html_sco_header.sco_footer()
)
elif tf[0] == -1:
return flask.redirect("editPartitionForm?formsemestre_id=" + formsemestre_id)
return flask.redirect(
"editPartitionForm?formsemestre_id=" + str(formsemestre_id)
)
else:
# form submission
return partition_set_name(
@ -1146,7 +1152,9 @@ def partition_set_name(context, partition_id, partition_name, REQUEST=None, redi
# redirect to partition edit page:
if redirect:
return flask.redirect("editPartitionForm?formsemestre_id=" + formsemestre_id)
return flask.redirect(
"editPartitionForm?formsemestre_id=" + str(formsemestre_id)
)
def group_set_name(context, group_id, group_name, REQUEST=None, redirect=1):
@ -1531,7 +1539,7 @@ def form_group_choice(
def make_query_groups(group_ids):
if group_ids:
return "&".join(["group_ids%3Alist=" + group_id for group_id in group_ids])
return "&".join(["group_ids%3Alist=" + str(group_id) for group_id in group_ids])
else:
return ""

View File

@ -353,7 +353,7 @@ def formsemestre_inscr_passage(
dest_url="formsemestre_inscr_passage",
add_headers=False,
cancel_url="formsemestre_inscr_passage?formsemestre_id="
+ formsemestre_id,
+ str(formsemestre_id),
OK="Effectuer l'opération",
parameters={
"formsemestre_id": formsemestre_id,

View File

@ -295,7 +295,7 @@ def ficheEtud(context, etudid=None, REQUEST=None):
),
)
alist.append(
'<tr><td><span class="annodate">Le %(date)s par %(zope_authenticated_user)s : </span><span class="annoc">%(comment)s</span></td>%(dellink)s</tr>'
'<tr><td><span class="annodate">Le %(date)s par %(author)s : </span><span class="annoc">%(comment)s</span></td>%(dellink)s</tr>'
% a
)
info["liste_annotations"] = "\n".join(alist)

View File

@ -95,9 +95,9 @@ def can_suppress_annotation(annotation_id):
if len(annos) != 1:
raise sco_exceptions.ScoValueError("annotation inexistante !")
anno = annos[0]
return (
current_user.user_name == anno["zope_authenticated_user"]
) or current_user.has_permission(Permission.ScoEtudAddAnnotations)
return (current_user.user_name == anno["author"]) or current_user.has_permission(
Permission.ScoEtudAddAnnotations
)
def can_edit_suivi():

View File

@ -321,7 +321,7 @@ def get_new_filename(context, etudid):
The path is constructed as: Fxx/etudid
"""
dept = scu.get_dept_id()
return find_new_dir() + dept + "_" + etudid
return find_new_dir() + dept + "_" + str(etudid)
def find_new_dir():

View File

@ -1123,13 +1123,13 @@ def _form_saisie_notes(context, E, M, group_ids, destination="", REQUEST=None):
explanation += '<span id="jurylink_%s" class="jurylink"></span>' % etudid
# Valeur actuelle du champ:
initvalues["note_" + etudid] = e["val"]
initvalues["note_" + str(etudid)] = e["val"]
label_link = '<a class="etudinfo" id="%s">%s</a>' % (etudid, label)
# Element de formulaire:
descr.append(
(
"note_" + etudid,
"note_" + str(etudid),
{
"size": 5,
"title": label_link,

View File

@ -211,7 +211,7 @@ def formsemestre_synchro_etuds(
dest_url="formsemestre_synchro_etuds",
add_headers=False,
cancel_url="formsemestre_synchro_etuds?formsemestre_id="
+ formsemestre_id,
+ str(formsemestre_id),
OK="Effectuer l'opération",
parameters={
"formsemestre_id": formsemestre_id,

View File

@ -1173,7 +1173,7 @@ def AddBilletAbsenceForm(context, etudid, REQUEST=None):
justified=tf[2]["justified"],
)
)
return flask.redirect("listeBilletsEtud?etudid=" + etudid)
return flask.redirect("listeBilletsEtud?etudid=" + str(etudid))
def _tableBillets(context, billets, etud=None, title=""):

View File

@ -40,6 +40,7 @@ from xml.etree import ElementTree
import flask
from flask import url_for, g
from flask import current_app
from flask_login import current_user
from config import Config
import scodoc_manager
@ -483,7 +484,7 @@ def formation_import_xml_form(context, REQUEST):
return flask.redirect(scu.NotesURL())
else:
formation_id, _, _ = sco_formations.formation_import_xml(
context, tf[2]["xmlfile"]
context, tf[2]["xmlfile"].read()
)
return (
@ -1078,7 +1079,9 @@ def edit_ue_expr(context, REQUEST, formsemestre_id, ue_id):
if tf[0] == 0:
return "\n".join(H) + tf[1] + html_sco_header.sco_footer()
elif tf[0] == -1:
return flask.redirect("formsemestre_status?formsemestre_id=" + formsemestre_id)
return flask.redirect(
"formsemestre_status?formsemestre_id=" + str(formsemestre_id)
)
else:
if el:
el[0]["computation_expr"] = tf[2]["computation_expr"]
@ -1091,7 +1094,7 @@ def edit_ue_expr(context, REQUEST, formsemestre_id, ue_id):
) # > modif regle calcul
return flask.redirect(
"formsemestre_status?formsemestre_id="
+ formsemestre_id
+ str(formsemestre_id)
+ "&head_message=règle%20de%20calcul%20modifiée"
)
@ -1329,7 +1332,7 @@ def etud_desinscrit_ue(context, etudid, formsemestre_id, ue_id, REQUEST=None):
return flask.redirect(
scu.ScoURL()
+ "/Notes/moduleimpl_inscriptions_stats?formsemestre_id="
+ formsemestre_id
+ str(formsemestre_id)
)
@ -1344,7 +1347,7 @@ def etud_inscrit_ue(context, etudid, formsemestre_id, ue_id, REQUEST=None):
return flask.redirect(
scu.ScoURL()
+ "/Notes/moduleimpl_inscriptions_stats?formsemestre_id="
+ formsemestre_id
+ str(formsemestre_id)
)
@ -1767,7 +1770,6 @@ def appreciation_add_form(
):
"form ajout ou edition d'une appreciation"
cnx = ndb.GetDBConnexion()
authuser = REQUEST.AUTHENTICATED_USER
if id: # edit mode
apps = sco_etud.appreciations_list(cnx, args={"id": id})
if not apps:
@ -1783,8 +1785,8 @@ def appreciation_add_form(
edit = 0
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
# check custom access permission
can_edit_app = (str(authuser) in sem["responsables"]) or (
authuser.has_permission(Permission.ScoEtudInscrit)
can_edit_app = (current_user.id in sem["responsables"]) or (
current_user.has_permission(Permission.ScoEtudInscrit)
)
if not can_edit_app:
raise AccessDenied("vous n'avez pas le droit d'ajouter une appreciation")
@ -1839,10 +1841,8 @@ def appreciation_add_form(
args = {
"etudid": etudid,
"formsemestre_id": formsemestre_id,
"author": str(authuser),
"author": current_user.user_name,
"comment": tf[2]["comment"],
"zope_authenticated_user": str(authuser),
"zope_remote_addr": REQUEST.REMOTE_ADDR,
}
if edit:
args["id"] = id

View File

@ -43,6 +43,7 @@ import psycopg2
import flask
from flask import g, url_for
from flask import current_app
from flask_login import current_user
from config import Config
import scodoc_manager
@ -454,18 +455,28 @@ sco_publish(
# Debouche / devenir etudiant
sco_publish(
"/itemsuivi_suppress", sco_debouche.itemsuivi_suppress, Permission.ScoEtudChangeAdr
"/itemsuivi_suppress",
sco_debouche.itemsuivi_suppress,
Permission.ScoEtudChangeAdr,
methods=["GET", "POST"],
)
sco_publish(
"/itemsuivi_create", sco_debouche.itemsuivi_create, Permission.ScoEtudChangeAdr
"/itemsuivi_create",
sco_debouche.itemsuivi_create,
Permission.ScoEtudChangeAdr,
methods=["GET", "POST"],
)
sco_publish(
"/itemsuivi_set_date", sco_debouche.itemsuivi_set_date, Permission.ScoEtudChangeAdr
"/itemsuivi_set_date",
sco_debouche.itemsuivi_set_date,
Permission.ScoEtudChangeAdr,
methods=["GET", "POST"],
)
sco_publish(
"/itemsuivi_set_situation",
sco_debouche.itemsuivi_set_situation,
Permission.ScoEtudChangeAdr,
methods=["GET", "POST"],
)
sco_publish(
"/itemsuivi_list_etud", sco_debouche.itemsuivi_list_etud, Permission.ScoView
@ -475,24 +486,25 @@ sco_publish(
"/itemsuivi_tag_search", sco_debouche.itemsuivi_tag_search, Permission.ScoView
)
sco_publish(
"/itemsuivi_tag_set", sco_debouche.itemsuivi_tag_set, Permission.ScoEtudChangeAdr
"/itemsuivi_tag_set",
sco_debouche.itemsuivi_tag_set,
Permission.ScoEtudChangeAdr,
methods=["GET", "POST"],
)
@bp.route("/doAddAnnotation", methods=["GET", "POST"])
@permission_required(Permission.ScoEtudAddAnnotations)
@scodoc7func(context)
def doAddAnnotation(context, etudid, comment, REQUEST):
def doAddAnnotation(etudid, comment):
"ajoute annotation sur etudiant"
authuser = REQUEST.AUTHENTICATED_USER
cnx = ndb.GetDBConnexion()
sco_etud.etud_annotations_create(
cnx,
args={
"etudid": etudid,
"comment": comment,
"zope_authenticated_user": str(authuser),
"zope_remote_addr": REQUEST.REMOTE_ADDR,
"authenticated_user": current_user.user_name,
},
)
logdb(cnx, method="addAnnotation", etudid=etudid)
@ -1473,7 +1485,7 @@ def _etudident_create_or_edit_form(context, REQUEST, edit):
formsemestre_id=formsemestre_id
) # > etudident_create_or_edit
#
return flask.redirect("ficheEtud?etudid=" + etudid)
return flask.redirect("ficheEtud?etudid=" + str(etudid))
@bp.route("/etudident_delete", methods=["GET", "POST"])
@ -1968,7 +1980,9 @@ def form_students_import_infos_admissions(context, REQUEST, formsemestre_id=None
return "\n".join(H) + tf[1] + help_text + F
elif tf[0] == -1:
return flask.redirect(
scu.ScoURL() + "/formsemestre_status?formsemestre_id=" + formsemestre_id
scu.ScoURL()
+ "/formsemestre_status?formsemestre_id="
+ str(formsemestre_id)
)
else:
return sco_import_etuds.students_import_admission(

View File

@ -15,9 +15,10 @@ BASEURL = "https://scodoc.xxx.net/ScoDoc/RT/Scolarite"
USER = "XXX"
PASSWORD = "XXX"
values = {'__ac_name' : USER,
'__ac_password' : PASSWORD,
}
values = {
"__ac_name": USER,
"__ac_password": PASSWORD,
}
# Configure memorisation des cookies:
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor())
@ -25,57 +26,74 @@ urllib2.install_opener(opener)
data = urllib.urlencode(values)
req = urllib2.Request(BASEURL, data) # this is a POST http request
req = urllib2.Request(BASEURL, data) # this is a POST http request
response = urllib2.urlopen(req)
# --- Use API
# Affiche la liste des formations en format XML
req = urllib2.Request(BASEURL+'/Notes/formation_list?format=xml' )
req = urllib2.Request(BASEURL + "/Notes/formation_list?format=xml")
response = urllib2.urlopen(req)
print response.read()[:100] # limite aux 100 premiers caracteres...
print response.read()[:100] # limite aux 100 premiers caracteres...
# Recupere la liste de tous les semestres:
req = urllib2.Request(BASEURL+'/Notes/formsemestre_list?format=json') # format json
req = urllib2.Request(BASEURL + "/Notes/formsemestre_list?format=json") # format json
response = urllib2.urlopen(req)
js_data = response.read()
# Plus amusant: va retrouver le bulletin de notes du premier etudiant (au hasard donc) du premier semestre (au hasard aussi)
try:
import json # Attention: ceci demande Python >= 2.6
import json # Attention: ceci demande Python >= 2.6
except:
import simplejson as json # python2.4 with simplejson installed
import simplejson as json # python2.4 with simplejson installed
data = json.loads(js_data) # decode la reponse JSON
data = json.loads(js_data) # decode la reponse JSON
if not data:
print "Aucun semestre !"
else:
formsemestre_id = str(data[0]['formsemestre_id'])
formsemestre_id = str(data[0]["formsemestre_id"])
# Obtient la liste des groupes:
req = urllib2.Request(BASEURL+'/Notes/formsemestre_partition_list?format=json&formsemestre_id='+formsemestre_id) # format json
req = urllib2.Request(
BASEURL
+ "/Notes/formsemestre_partition_list?format=json&formsemestre_id="
+ str(formsemestre_id)
) # format json
response = urllib2.urlopen(req)
js_data = response.read()
data = json.loads(js_data)
group_id = data[0]['group'][0]['group_id'] # premier groupe (normalement existe toujours)
group_id = data[0]["group"][0][
"group_id"
] # premier groupe (normalement existe toujours)
# Liste les étudiants de ce groupe:
req = urllib2.Request(BASEURL+'/Notes/group_list?format=json&with_codes=1&group_id='+group_id) # format json
req = urllib2.Request(
BASEURL + "/Notes/group_list?format=json&with_codes=1&group_id=" + str(group_id)
) # format json
response = urllib2.urlopen(req)
js_data = response.read()
data = json.loads(js_data)
# Le code du premier étudiant:
if not data:
print "pas d'etudiants dans ce semestre !"
print ("pas d'etudiants dans ce semestre !")
else:
etudid = data[0]['etudid']
etudid = data[0]["etudid"]
# Récupère bulletin de notes:
req = urllib2.Request(BASEURL+'/Notes/formsemestre_bulletinetud?formsemestre_id='+formsemestre_id+'&etudid=' + etudid + '&format=xml') # format XML ici !
req = urllib2.Request(
BASEURL
+ "/Notes/formsemestre_bulletinetud?formsemestre_id="
+ str(formsemestre_id)
+ "&etudid="
+ str(etudid)
+ "&format=xml"
) # format XML ici !
response = urllib2.urlopen(req)
xml_bulletin = response.read()
print '----- Bulletin de notes en XML:'
print "----- Bulletin de notes en XML:"
print xml_bulletin
# Récupère la moyenne générale:
import xml.dom.minidom
doc = xml.dom.minidom.parseString(xml_bulletin)
moy = doc.getElementsByTagName('note')[0].getAttribute('value') # une chaine unicode
print '\nMoyenne generale: ', moy
doc = xml.dom.minidom.parseString(xml_bulletin)
moy = doc.getElementsByTagName("note")[0].getAttribute(
"value"
) # une chaine unicode
print "\nMoyenne generale: ", moy