Blamiblog

Posar notes massivament al Moodle

Posted in Avatars tècnics by blami on 1 Novembre 2010

[20120604] Actualització: pots trobar la darrera versió d’aquest script a les entrades del github: ies_preparanotes.py i ies_posanotes.py

Doncs ara que ja tinc la descàrrega massiva d’exercicis del Moodle, m’he volgut fer un nou script per a solucionar una altra de les tasques que em fan perdre temps: posar les notes.

Ja saps. El Moodle t’obliga a posar-les de una en una. Tens risc d’error i la velocitat depèn de com estigui de carregada la xarxa.

El script que he preparat, agafa un .csv amb les notes i comentaris associats al nr. intern de cada alumne i, a partir del nr. intern de l’exercici, penja les notes i comentaris.

Està una mica més treballadet que la versió de descàrrega, però encara li queda molta feina si el volgués deixar per presumir.

En tot cas, te’l deixo per si et serveix.

#! /usr/bin/python
# encoding: utf-8
#
# Descr:    Posa notes a un exercici de moodle
#           Les notes han d'estar incloses a un fitxer .csv
#           amb el format:
#               id alumne ^ nota (100) ^ comentari
#
import sys, os
import optparse
import mechanize
import getpass
import csv
#
_URL_BASE  = 'http://url.del.teu.moodle.org' # url base del lloc moodle
_URL_LOGIN = _URL_BASE + '/login/index.php'           # url del login
_URL_EX    = _URL_BASE + '/mod/assignment/submissions.php?id=%s' # url del lliurament
_ID_FORM_LLIURAMENTS = 'fastg'                  # id del formulari amb els lliuraments
#
def connecta(username, password):
    """connecta i retorna el browser"""
    # TODO: caldrà comprovar que s'ha fet correctament el login
    try:
        br = mechanize.Browser()
        br.open(_URL_LOGIN)
        br.select_form(nr=1)            # TODO: caldria fer cercar-lo per id
        br.form['username']=username
        br.form['password']=password
        br.submit()
        print "Autenticat"
    except:
        print >> sys.stderr, "Error: no es pot fer login"
        br = None
    return br
#
def carreganotes(fitxer):
    """ carrega les notes del fitxer i les retorna en forma de diccionari
    amb clau id d'estudiant i valor la tupla (nota, comentari) """
    try:
        f = open(fitxer)
        reader = csv.reader(f, delimiter='^')
        notes = dict()
        for linia in reader:
            if len(linia)!=3:
                print >> sys.stderr, "Error: format incorrecte del fitxer. Linia:%s"%linia
                raise Exception()
            notes[linia[0].strip()] = (linia[1].strip(), linia[2].strip())
        f.close()
    except:
        print >> sys.stderr, "Error carregant les notes del fitxer %s"%fitxer
        notes = None
    return notes
#
def extreunum(s):
    """ extreu el número de un nom de control com ara 'menu[25]' """
    resultat = ''
    try:
        resultat = s.split("[")[1][:-1]
    except:
        pass
    return resultat
#
def trobaformindex(br, id):
    """ troba al browser el formulari amb identificador id i retorna
    la seva posició. -1 si no el troba """
    index = 0
    trobat = False
    for f in br.forms():
        if 'id' in f.attrs and f.attrs['id']==id:
            trobat = True
            break
        index += 1
    if not trobat:
        index = -1
    return index
#
def posanotes(notes, br):
    """ posa les notes a l'exercici. Retorna True si tot correcte. """
    #
    index = trobaformindex(br, _ID_FORM_LLIURAMENTS)
    if index < 0:         print >>sys.stderr, "Error: no s'ha trobat el formulari de lliuraments"
        return False
    br.select_form(nr=index)
    for c in br.controls:
        if c.name.startswith("menu["):
            idestudiant = extreunum(c.name)
            if idestudiant in notes:
                nota = notes[idestudiant][0]
            else:
                nota = '-1'   # no es disposa de nota
            c.value=[nota]
        if c.name.startswith("submissioncomment["):
            idestudiant = extreunum(c.name)
            if idestudiant in notes:
                c.value=notes[idestudiant][1]
    #
    br.submit()
    return True # tot correcte
#
def main():
    p = optparse.OptionParser(description=u"Posa notes d'un exercici de moodle",
        version="1.0")
    p.add_option("-n", "--numexercici", action="store", help=u"Número identificador de l'exercici", nargs=1, dest="numexercici")
    p.add_option("-f", "--fitxer", action="store", help=u"Fitxer que conté les notes en format csv", nargs=1, dest="fitxer")
    p.add_option("-u", "--username", action="store", help=u"Login de l'usuari", nargs=1, dest="username")
    p.add_option("-p", "--password", action="store", help=u"Password de l'usuari", nargs=1, dest="password")
    opcions, arguments = p.parse_args()
    if not opcions.numexercici:
        print >> sys.stderr, "Error: Cal indicar el número de l'exercici a descarregar"
        return -1
    if not opcions.fitxer:
        print >> sys.stderr, "Error: Cal indicar el fitxer que conté les notes"
        return -1
    #
    notes = carreganotes(opcions.fitxer)
    if not notes: return -1
    #
    if not opcions.username:
        username = raw_input(      "Usuari:   ")
    else:
        username = opcions.username
    if not opcions.password:
        password = getpass.getpass("Password: ")
    else:
        password = opcions.password
    #
    br = connecta(username, password)
    if not br: return -1
    br.open(_URL_EX%opcions.numexercici)
    print "Carregada la pàgina de l'exercici %s"%opcions.numexercici
    #
    if posanotes(notes, br):
       print "Notes assignades"
    else:
       return -1
    return 0
#
if __name__=="__main__":
    sys.exit(main())
Anuncis

11 Respostes

Subscribe to comments with RSS.

  1. cerratis said, on 1 Novembre 2010 at 19:48

    Impresionante!!!

    • blami said, on 5 Novembre 2010 at 21:47

      Hombre, es mucho más impresionante el código de la biblioteca mechanize pero gracias 😉

  2. domingo said, on 26 Setembre 2011 at 12:06

    Muchas gracias!
    Es genial, no sabia que ya estaba hecho.
    Pero me has salvado la vida.
    Un saludo,
    Domingo

    • blami said, on 26 Setembre 2011 at 13:50

      Me alegro de que te sirva. Un saludo

  3. domingo said, on 29 Setembre 2011 at 10:47

    Hola, soy yo otra vez, no quiero ser pesado pero
    ahora no se porque me ha dado error

    Autenticat
    Carregada la pàgina de l’exercici 14233
    Error: no s’ha trobat el formulari de lliuraments

    Vale, eso quiere decir que no ha encontrado la pagina de entregas.
    Bueno, pues intente hacer debugging y en la funcion
    trobaformindex no encuentra uno que se llame fastbg (que es el
    _ID_FORM_LLIURAMENTS, esto es lo que encuentra.

    {‘action’: ‘http://moodle.unican.es/course/mod.php’, ‘onsubmit’: “this.target=’_top’; return true”, ‘method’: ‘get’}
    {‘action’: ‘http://moodle.unican.es/course/jumpto.php’, ‘id’: ‘selectgroup’, ‘class’: ‘popupform’, ‘method’: ‘get’}
    {‘action’: ‘submissions.php?id=14233’, ‘id’: ‘options’, ‘method’: ‘post’}

    ¿Se te ocurre algo que pueda estar haciendo mal?
    Un saludo,
    Domingo
    P.d. Otra cosa, se sacar las ids de los estudiantes una a una (pinchando en su pagina), pero
    no se sacarlas todas a la vez, con su nombre. ¿Se te ocurre algo?

    • blami said, on 29 Setembre 2011 at 11:51

      Hola Domingo

      Reconozco que después de un año ya me acuerdo muy poco del código. Con todo, me va bien refrescar pues lo quiero volver a usar este curso.

      Respecto a la primera pregunta y tan sólo para descartar, te propongo que crees un ejercicio “test” en el moodle, entres con el navegador a la página de entregas donde recogerías los ejercicios manualmente y te apuntes el número final que sale en la url. Por ejemplo http://moodle.tusitio.org/mod/assignment/submissions.php?id=13741. Prueba a usar este número con los scripts y dime que tal.

      Respecto a la obtención masiva de las ids de los estudiantes, si me aceptas una manera “guarrona”, puedes mirar el código fuente de la página de entregas que has hecho antes y jugando un poco con filtros puedes acabar obteniendo la asociación nombre/moodle_id.

      …class=”cell c1 fullname”…Nombre Completo Alumno…id=”g675“…

      Espero que te sirva

      • domingo said, on 29 Setembre 2011 at 11:59

        Hola Blami y gracias por responder.
        He creado un ejercicio y el numero que me sale es 14223
        Esta es la pagina donde estan todos los estudiantes que han entregado las practicas.

        http://moodle.unican.es/mod/assignment/submissions.php?id=14233

        El error que me da es el mismo.
        Una cosa, ¿podria ser porque no utilizo la calificacion rapida?
        Sobre las soluciones, tienes tu razon, la solucion guarrona me sirve.

  4. domingo said, on 29 Setembre 2011 at 12:11

    Vale, era simplemente que tenia que activar la calificacion rapida.
    Gracias por tu ayuda, de todas formas creo que voy a hacer un pequeño programa python
    para sacar todos los numeros de los usuarios.

    • blami said, on 29 Setembre 2011 at 13:35

      Me alegro de que lo hayas resuelto.

      El script que colgué depende mucho (demasiado) de la estructura del documento html. Incluso es fácil que falle para versiones diferentes del moodle.

      He pensado un poco más el tema de los números. Es posible que a ti no te interese el id interno de Moodle (yo lo uso precisamente para ocultarme el nombre y así valorar sin saber a qué alumno corrijo) En ese caso, simplemente tendrías que modificar un poco el código (para que, en lugar de buscar el elemento “menu[*]” recogiese el valor que aparece tras el tag fullname.

      • domingo said, on 29 Setembre 2011 at 15:53

        Anda, que idea mas buena!
        Oye, este fin de semana lo voy a cambiar y ya que tu has creado la primera parte
        del script, te envio esta modificacion por si quieres compartirla.
        Muchas gracias!

      • blami said, on 29 Setembre 2011 at 16:19

        Genial. Aunque, si tienes un blog y decides ponerlo allá, te enlazo y ya está. A fin de cuentas no creo que para quien lo pueda usar en un futuro le sea de mucha utilidad saber quién lo ha hecho 😉


Deixa un comentari

Fill in your details below or click an icon to log in:

WordPress.com Logo

Esteu comentant fent servir el compte WordPress.com. Log Out / Canvia )

Twitter picture

Esteu comentant fent servir el compte Twitter. Log Out / Canvia )

Facebook photo

Esteu comentant fent servir el compte Facebook. Log Out / Canvia )

Google+ photo

Esteu comentant fent servir el compte Google+. Log Out / Canvia )

Connecting to %s

%d bloggers like this: