Voti degli allegati e pass-back dei voti

Questa è la sesta procedura dettagliata dei componenti aggiuntivi di Classroom di una serie di procedure dettagliate.

In questa procedura dettagliata, modificherai l'esempio del passaggio precedente per produrre un allegato di tipo attività con valutazione. Inoltre, trasmetti un voto a Google Classroom in modo programmatico, come appare nel voto dell'insegnante libro come voto provvisorio.

Questa procedura dettagliata differisce leggermente dalle altre della serie in quanto due possibili approcci per ritrasmettere i voti a di Classroom. Entrambi hanno un impatto distinto sullo sviluppatore e sull'utente esperienze; prendi in considerazione entrambi gli aspetti quando progetti il componente aggiuntivo di Classroom. Per ulteriori informazioni, consulta la pagina della guida sull'interazione con gli allegati. le opzioni di implementazione.

Tieni presente che le funzionalità di valutazione nell'API sono facoltative. Possono essere utilizzate con Qualsiasi allegato di tipo attività.

Nel corso di questa procedura dettagliata, completerai quanto segue:

  • Modifica le richieste di creazione degli allegati precedenti nel API Classroom per impostare anche il denominatore di voto dell'allegato.
  • Assegna un punteggio programmatico ai contenuti inviati dallo studente e all'impostazione numeratore del voto.
  • Implementa due approcci per superare il voto dei contenuti inviati Classroom utilizzando le credenziali degli insegnanti che hanno effettuato l'accesso o che sono offline.

Al termine, i voti vengono visualizzati nel registro di Classroom dopo il un comportamento di pass-back Il momento esatto in cui ciò accade dipende l'approccio all'implementazione.

Ai fini di questo esempio, riutilizza l'attività della precedente procedura dettagliata in cui a uno studente viene mostrata l'immagine di un monumento famoso che viene richiesto di inserire il nome. Assegna un voto completo all'allegato se lo studente inserisce il nome corretto, altrimenti zero.

Comprendere la funzionalità di valutazione dell'API Classroom componenti aggiuntivi

Il componente aggiuntivo può impostare sia il numeratore del voto sia il denominatore del voto per un allegato. Queste vengono impostate rispettivamente utilizzando gli attributi pointsEarned e maxPoints i valori nell'API. Una scheda degli allegati nella UI di Classroom mostra il valore maxPoints quando è stato impostato.

Esempio di più allegati con maxPoints su uno
compito

Figura 1. L'interfaccia utente per la creazione dei compiti, con tre schede di allegati aggiuntivi che hai impostato maxPoints.

L'API Classroom add-ons consente di configurare le impostazioni e il punteggio ottenuto per i voti attachment. Non corrispondono ai voti di compiti. Tuttavia, le impostazioni dei voti del compito seguono impostazioni dei voti dell'allegato con l'etichetta Sincronizzazione voti attiva relativa alla scheda degli allegati. Quando viene visualizzata la colonna "Sincronizzazione voti" un allegato imposta pointsEarned per un inviati dallo studente, imposta anche il voto provvisorio dello studente per il compito.

Di solito, il primo allegato aggiunto al compito che imposta maxPoints riceve l'opzione "Sincronizzazione voti" dell'etichetta. Visualizzare l'interfaccia utente per la creazione dei compiti esempio mostrato nella Figura 1 per un esempio della funzionalità dell'etichetta. Tieni presente che l'"Allegato 1" contiene la dicitura "Sincronizzazione voti" e che il voto del compito nella casella rossa è stato aggiornato a 50 punti. Inoltre, sebbene la Figura 1 mostra tre schede per gli allegati, una sola contiene la dicitura "Sincronizzazione voti" dell'etichetta. Questo è un limite fondamentale dell'implementazione corrente: un solo allegato può contenere in "Sincronizzazione voti" dell'etichetta.

Se sono presenti più allegati con maxPoints impostato, rimuovendo il valore allegato con "Sincronizzazione voti" non attiva l'opzione "Sincronizzazione voti" su uno qualsiasi dei allegati rimanenti. L'aggiunta di un altro allegato che imposta maxPoints consente Sincronizza i voti sul nuovo allegato e il voto massimo del compito viene modificato in corrispondono. Non esiste un meccanismo per vedere in modo programmatico quale allegato include "Sincronizzazione voti" né vedere quanti allegati ha un determinato compito.

Impostare il voto massimo per un allegato

Questa sezione descrive l'impostazione del denominatore per il voto dell'allegato; che è il punteggio massimo che tutti gli studenti possono ottenere contenuti inviati. Per farlo, imposta il valore maxPoints dell'allegato.

È necessaria solo una piccola modifica alla nostra implementazione esistente per consentire le funzionalità di valutazione. Quando crei un allegato, aggiungi il valore maxPoints in lo stesso oggetto AddOnAttachment che contiene studentWorkReviewUri, teacherViewUri e altri campi degli allegati.

Tieni presente che il punteggio massimo predefinito per un nuovo compito è 100. Ti suggeriamo maxPoints su un valore diverso da 100, in modo da poter verificare che voti siano impostati correttamente. Imposta maxPoints su 50 come dimostrazione:

Python

Aggiungi il campo maxPoints durante la creazione dell'oggetto attachment, è sufficiente prima di inviare una richiesta CREATE Endpoint courses.courseWork.addOnAttachments. Puoi trovarlo nel webapp/attachment_routes.py se segui l'esempio fornito.

attachment = {
    # Specifies the route for a teacher user.
    "teacherViewUri": {
        "uri":
            flask.url_for(
                "load_activity_attachment",
                _scheme='https',
                _external=True),
    },
    # Specifies the route for a student user.
    "studentViewUri": {
        "uri":
            flask.url_for(
                "load_activity_attachment",
                _scheme='https',
                _external=True)
    },
    # Specifies the route for a teacher user when the attachment is
    # loaded in the Classroom grading view.
    "studentWorkReviewUri": {
        "uri":
            flask.url_for(
                "view_submission", _scheme='https', _external=True)
    },
    # Sets the maximum points that a student can earn for this activity.
    # This is the denominator in a fractional representation of a grade.
    "maxPoints": 50,
    # The title of the attachment.
    "title": f"Attachment {attachment_count}",
}

Ai fini di questa dimostrazione, memorizzi anche il valore maxPoints in il database degli allegati locale; senza dover effettuare un'ulteriore chiamata API in un secondo momento, quando valutano i compiti degli studenti. Tieni presente, tuttavia, che è possibile che Gli insegnanti possono modificare le impostazioni dei voti dei compiti indipendentemente dal componente aggiuntivo. Invia una richiesta GET all'endpoint courses.courseWork per visualizzare Valore maxPoints a livello di assegnazione. Durante questa operazione, passa il valore itemId nel CourseWork.id.

Ora aggiorna il modello del tuo database in modo che contenga anche il valore maxPoints dell'allegato. Ti consigliamo di utilizzare il valore maxPoints della risposta CREATE:

Python

Innanzitutto, aggiungi un campo max_points alla tabella Attachment. Puoi trovare questo nel file webapp/models.py, se segui l'esempio fornito.

# Database model to represent an attachment.
class Attachment(db.Model):
    # The attachmentId is the unique identifier for the attachment.
    attachment_id = db.Column(db.String(120), primary_key=True)

    # The image filename to store.
    image_filename = db.Column(db.String(120))

    # The image caption to store.
    image_caption = db.Column(db.String(120))

    # The maximum number of points for this activity.
    max_points = db.Column(db.Integer)

Torna alla richiesta courses.courseWork.addOnAttachments CREATE. Negozio il valore maxPoints restituito nella risposta.

new_attachment = Attachment(
    # The new attachment's unique ID, returned in the CREATE response.
    attachment_id=resp.get("id"),
    image_filename=key,
    image_caption=value,
    # Store the maxPoints value returned in the response.
    max_points=int(resp.get("maxPoints")))
db.session.add(new_attachment)
db.session.commit()

Ora l'allegato ha un voto massimo. Dovresti essere in grado di verificare questo comportamento ora; aggiungere un allegato a un nuovo compito e osserva che la scheda dell'allegato mostra la sezione "Sincronizzazione voti" e i "Punti" del compito modifiche ai valori.

Impostare un voto inviato da uno studente in Classroom

Questa sezione descrive l'impostazione del numeratore per il voto dell'allegato; cioè il punteggio di un singolo studente per l'allegato. Per farlo, imposta uno studente valore pointsEarned dell'invio.

Ora devi prendere una decisione importante: in che modo il tuo componente aggiuntivo dovrebbe di impostare pointsEarned?

Il problema è che l'impostazione di pointsEarned richiede l'teacherambito OAuth. Non devi concedere l'ambito teacher agli utenti studenti. Questo potrebbe comportare comportamenti imprevisti durante l'interazione degli studenti con il componente aggiuntivo, ad esempio iframe di Vista insegnante anziché di Vista studente. Di conseguenza, hai due scelte per l'impostazione di pointsEarned:

  • Con le credenziali dell'insegnante che ha eseguito l'accesso.
  • Utilizzo delle credenziali degli insegnanti archiviate (offline).

Le seguenti sezioni discutono i compromessi di ciascun approccio prima di ogni implementazione. Tieni presente che gli esempi forniti dimostrano entrambi gli approcci per passare un voto in Classroom; vedi il le istruzioni specifiche per ogni lingua riportate di seguito per scoprire come scegliere un approccio eseguendo gli esempi forniti:

Python

Trova la dichiarazione SET_GRADE_WITH_LOGGED_IN_USER_CREDENTIALS in alto di webapp/attachment_routes.py file. Imposta questo valore su True per ritrasmettere i voti utilizzando le credenziali dell'insegnante che ha effettuato l'accesso. Imposta questo valore su False di ritrasmettere i voti utilizzando le credenziali memorizzate quando lo studente invia la attività.

Impostare i voti utilizzando le credenziali dell'insegnante che ha effettuato l'accesso

Utilizza le credenziali dell'utente che ha eseguito l'accesso per inviare la richiesta di impostare pointsEarned. Questo approccio dovrebbe sembrare molto intuitivo, in quanto rispecchia il resto dell'implementazione e richiede uno sforzo minimo per essere realizzato.

Tuttavia, tieni presente che l'insegnante interagisce solo con i inviato nell'iframe della revisione del lavoro dello studente. Questo ha importanti implicazioni:

  • I voti non vengono inseriti in Classroom finché l'insegnante non completa nell'interfaccia utente di Classroom.
  • Un insegnante potrebbe dover aprire tutti i contenuti inviati dagli studenti per compilare tutti voti degli studenti.
  • Si verifica un breve ritardo tra la ricezione del voto in Classroom e il suo aspetto nella UI di Classroom. Il ritardo è solitamente da cinque a dieci secondi, ma può durare anche 30 secondi.

La combinazione di questi fattori fa sì che gli insegnanti lavoro manuale notevole e dispendioso in termini di tempo per compilare tutti i voti di un corso.

Per implementare questo approccio, aggiungi un'altra chiamata API allo studente esistente Percorso per la revisione del lavoro.

Dopo aver recuperato i record inviati e degli allegati degli studenti, valuta contenuti inviati dallo studente e archivia il voto risultante. Imposta il voto nel Campo pointsEarned di un oggetto AddOnAttachmentStudentSubmission. Infine, invia una richiesta PATCH a endpoint courses.courseWork.addOnAttachments.studentSubmissions con AddOnAttachmentStudentSubmission nel corpo della richiesta. Tieni presente che Inoltre, devi specificare pointsEarned nel campo updateMask della richiesta PATCH:

Python

# Look up the student's submission in our database.
student_submission = Submission.query.get(flask.session["submissionId"])

# Look up the attachment in the database.
attachment = Attachment.query.get(student_submission.attachment_id)

grade = 0

# See if the student response matches the stored name.
if student_submission.student_response.lower(
) == attachment.image_caption.lower():
    grade = attachment.max_points

# Create an instance of the Classroom service.
classroom_service = ch._credential_handler.get_classroom_service()

# Build an AddOnAttachmentStudentSubmission instance.
add_on_attachment_student_submission = {
    # Specifies the student's score for this attachment.
    "pointsEarned": grade,
}

# Issue a PATCH request to set the grade numerator for this attachment.
patch_grade_response = classroom_service.courses().courseWork(
).addOnAttachments().studentSubmissions().patch(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"],
    attachmentId=flask.session["attachmentId"],
    submissionId=flask.session["submissionId"],
    # updateMask is a list of fields being modified.
    updateMask="pointsEarned",
    body=add_on_attachment_student_submission).execute()

Impostare i voti utilizzando le credenziali degli insegnanti offline

Il secondo approccio all'impostazione dei voti prevede l'uso di credenziali memorizzate. per l'insegnante che ha creato l'allegato. Questa implementazione richiede che crei le credenziali utilizzando l'aggiornamento di un insegnante precedentemente autorizzato di accesso ai token di accesso e usa queste credenziali per impostare pointsEarned.

Un vantaggio fondamentale di questo approccio è che i voti si completano senza richiedere dell'insegnante nella UI di Classroom, evitando i problemi menzionati sopra. Il risultato è che gli utenti finali percepiscono l'esperienza di valutazione in modo semplice ed efficiente. Inoltre, questo approccio ti consente di scegliere momento in cui ritrasmetti i voti, ad esempio quando gli studenti completano attività fisica o in modo asincrono.

Completa le seguenti attività per implementare questo approccio:

  1. Modificare i record del database degli utenti per archiviare un token di accesso.
  2. Modificare i record del database degli allegati per archiviare un ID insegnante.
  3. Recupera le credenziali dell'insegnante e, facoltativamente, costruiscine una nuova Istanza del servizio Classroom.
  4. Imposta il voto di un invio.

Ai fini di questa dimostrazione, imposta il voto quando lo studente completa l'attività; ovvero quando lo studente invia il modulo nella vista studente percorso.

Modifica i record del database utente per archiviare il token di accesso

Per effettuare chiamate API sono necessari due token univoci: il token di aggiornamento e il token token di accesso. Se finora hai seguito la procedura dettagliata della serie, Lo schema della tabella User dovrebbe già archiviare un token di aggiornamento. Memorizzazione dell'aggiornamento sia sufficiente quando effettui chiamate API solo con l'utente che ha eseguito l'accesso, ricevi un token di accesso nell'ambito del flusso di autenticazione.

Tuttavia, ora devi effettuare chiamate come utente diverso dall'utente che ha eseguito l'accesso, il che significa che il flusso di autenticazione non è disponibile. Devi quindi archiviare insieme al token di aggiornamento. Aggiorna lo schema della tabella User a includi un token di accesso:

Python

Nell'esempio fornito, si trova nel file webapp/models.py.

# Database model to represent a user.
class User(db.Model):
    # The user's identifying information:
    id = db.Column(db.String(120), primary_key=True)
    display_name = db.Column(db.String(80))
    email = db.Column(db.String(120), unique=True)
    portrait_url = db.Column(db.Text())

    # The user's refresh token, which will be used to obtain an access token.
    # Note that refresh tokens will become invalid if:
    # - The refresh token has not been used for six months.
    # - The user revokes your app's access permissions.
    # - The user changes passwords.
    # - The user belongs to a Google Cloud organization
    #   that has session control policies in effect.
    refresh_token = db.Column(db.Text())

    # An access token for this user.
    access_token = db.Column(db.Text())

Quindi, aggiorna tutti i codici che creano o aggiornano un record User per memorizzare anche token di accesso:

Python

Nell'esempio fornito, si trova nel file webapp/credential_handler.py.

def save_credentials_to_storage(self, credentials):
    # Issue a request for the user's profile details.
    user_info_service = googleapiclient.discovery.build(
        serviceName="oauth2", version="v2", credentials=credentials)
    user_info = user_info_service.userinfo().get().execute()
    flask.session["username"] = user_info.get("name")
    flask.session["login_hint"] = user_info.get("id")

    # See if we have any stored credentials for this user. If they have used
    # the add-on before, we should have received login_hint in the query
    # parameters.
    existing_user = self.get_credentials_from_storage(user_info.get("id"))

    # If we do have stored credentials, update the database.
    if existing_user:
        if user_info:
            existing_user.id = user_info.get("id")
            existing_user.display_name = user_info.get("name")
            existing_user.email = user_info.get("email")
            existing_user.portrait_url = user_info.get("picture")

        if credentials and credentials.refresh_token is not None:
            existing_user.refresh_token = credentials.refresh_token
            # Update the access token.
            existing_user.access_token = credentials.token

    # If not, this must be a new user, so add a new entry to the database.
    else:
        new_user = User(
            id=user_info.get("id"),
            display_name=user_info.get("name"),
            email=user_info.get("email"),
            portrait_url=user_info.get("picture"),
            refresh_token=credentials.refresh_token,
            # Store the access token as well.
            access_token=credentials.token)

        db.session.add(new_user)

    db.session.commit()

Modificare i record del database degli allegati per archiviare un ID insegnante

Per impostare un voto per un'attività, chiama per impostare pointsEarned come insegnante del corso. Puoi farlo in diversi modi:

  • Archivia una mappatura locale delle credenziali degli insegnanti agli ID corso. Tuttavia, tieni presente è possibile che lo stesso insegnante non sia sempre associato a un determinato corso.
  • Invia richieste GET all'endpoint courses dell'API Classroom per trova gli insegnanti attuali. Quindi, esegui una query nei record utente locali per individuare credenziali dell'insegnante corrispondenti.
  • Quando crei un allegato di un componente aggiuntivo, memorizza un ID insegnante nella nel database degli allegati. Quindi, recupera le credenziali dell'insegnante dal attachmentId passato all'iframe della vista studente.

Questo esempio mostra l'ultima opzione, dato che stai impostando i voti quando lo studente completa un allegato di attività.

Aggiungi un campo ID insegnante alla tabella Attachment del database:

Python

Nell'esempio fornito, si trova nel file webapp/models.py.

# Database model to represent an attachment.
class Attachment(db.Model):
    # The attachmentId is the unique identifier for the attachment.
    attachment_id = db.Column(db.String(120), primary_key=True)

    # The image filename to store.
    image_filename = db.Column(db.String(120))

    # The image caption to store.
    image_caption = db.Column(db.String(120))

    # The maximum number of points for this activity.
    max_points = db.Column(db.Integer)

    # The ID of the teacher that created the attachment.
    teacher_id = db.Column(db.String(120))

Quindi, aggiorna qualsiasi codice che crea o aggiorna un record Attachment per memorizza l'ID del creator:

Python

Nell'esempio fornito, è nel metodo create_attachments nella webapp/attachment_routes.py file.

# Store the attachment by id.
new_attachment = Attachment(
    # The new attachment's unique ID, returned in the CREATE response.
    attachment_id=resp.get("id"),
    image_filename=key,
    image_caption=value,
    max_points=int(resp.get("maxPoints")),
    teacher_id=flask.session["login_hint"])
db.session.add(new_attachment)
db.session.commit()

Recupera le credenziali dell'insegnante

Trova il percorso che pubblica l'iframe della vista studente. Subito dopo l'archiviazione la risposta dello studente nel tuo database locale, recupera le credenziali del tuo spazio di archiviazione locale. Questo dovrebbe essere chiaro dato e la preparazione del modello nei due passaggi precedenti. Puoi anche usarli per creare una nuova istanza del servizio Classroom per l'utente insegnante:

Python

Nell'esempio fornito, è nel metodo load_activity_attachment in il file webapp/attachment_routes.py.

# Create an instance of the Classroom service using the tokens for the
# teacher that created the attachment.

# We're assuming that there are already credentials in the session, which
# should be true given that we are adding this within the Student View
# route; we must have had valid credentials for the student to reach this
# point. The student credentials will be valid to construct a Classroom
# service for another user except for the tokens.
if not flask.session.get("credentials"):
    raise ValueError(
        "No credentials found in session for the requested user.")

# Make a copy of the student credentials so we don't modify the original.
teacher_credentials_dict = deepcopy(flask.session.get("credentials"))

# Retrieve the requested user's stored record.
teacher_record = User.query.get(attachment.teacher_id)

# Apply the user's tokens to the copied credentials.
teacher_credentials_dict["refresh_token"] = teacher_record.refresh_token
teacher_credentials_dict["token"] = teacher_record.access_token

# Construct a temporary credentials object.
teacher_credentials = google.oauth2.credentials.Credentials(
    **teacher_credentials_dict)

# Refresh the credentials if necessary; we don't know when this teacher last
# made a call.
if teacher_credentials.expired:
    teacher_credentials.refresh(Request())

# Request the Classroom service for the specified user.
teacher_classroom_service = googleapiclient.discovery.build(
    serviceName=CLASSROOM_API_SERVICE_NAME,
    version=CLASSROOM_API_VERSION,
    credentials=teacher_credentials)

Impostare il voto di un invio

La procedura qui descritta è identica a quella di utilizzare la credenziali. Tuttavia, tieni presente che devi effettuare la chiamata con l'insegnante credenziali recuperate nel passaggio precedente:

Python

# Issue a PATCH request as the teacher to set the grade numerator for this
# attachment.
patch_grade_response = teacher_classroom_service.courses().courseWork(
).addOnAttachments().studentSubmissions().patch(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"],
    attachmentId=flask.session["attachmentId"],
    submissionId=flask.session["submissionId"],
    # updateMask is a list of fields being modified.
    updateMask="pointsEarned",
    body=add_on_attachment_student_submission).execute()

Testa il componente aggiuntivo

Come nella procedura dettagliata precedente, crea un compito con un tipo di attività allegato come insegnante, inviare una risposta come studente, quindi aprire inviato nell'iframe della revisione del lavoro dello studente. Dovresti riuscire a vedere vengono visualizzati in momenti diversi a seconda dell'approccio all'implementazione:

  • Se scegli di ritrasmettere il voto quando lo studente ha completato l'attività, dovresti vedere il voto provvisorio nell'interfaccia utente prima di aprire iframe per la revisione del lavoro dello studente. Puoi anche visualizzarla nell'elenco degli studenti quando aprire il compito e nella sezione accanto a Lavoro dello studente Esamina iframe.
  • Se hai scelto di ritrasmettere un voto quando l'insegnante apre il Lavoro dello studente Rivedi l'iframe; il voto deve apparire nella sezione "Voto". immediatamente dopo viene caricato l'iframe. Come menzionato sopra, questa operazione può richiedere fino a 30 secondi. Dopodiché, il voto per lo studente specifico deve apparire anche nel altre visualizzazioni del registro di Classroom.

Verifica che venga visualizzato il punteggio corretto per lo studente.

Complimenti! È tutto pronto per andare al passaggio successivo: creazione di allegati al di fuori di Google Classroom.