API:Afficheur de l'image du jour

From mediawiki.org
Jump to navigation Jump to search
This page is a translated version of the page API:Picture of the day viewer and the translation is 78% complete.

Présentation

Ce tutoriel vous apprendra comment faire un afficheur pour l'Image du jour de Wikipedia en utilisant l'API Action de MediaWiki.

Télécharger le code de GitHub Voir l'application dans Toolforge

Ce tutoriel vous montrera comment le faire avec :

Processus pas à pas pour construire cette application

Etape 1 installer l'environnement de développement Python et Flask

Configurer Python

Ce tutoriel utilise Python 3. Vous pouvez télécharger la dernière version de Python à partir de :

Voir le Guide Python du débutant pour les instructions concernant l'installation de Python sur les autres systèmes d'exploitation.

Configurer Flask

Pip est un gestionnaire de paquets que vous pouvez utiliser pour installer Flask : pip install flask. Si vous ne disposez pas de pip, installez-le à partir du site web Pip officiel


Etape 2 créer une application Flask simple

Si tout s'est correctement installé, copiez le script suivant dans app.py, à l'intérieur du dossier du projet : $HOME/picture-of-the-day-viewer/app.py. Lorsque vous l'exécutez, il doit afficher « Hello world » sur http://localhost:5000/:

#!/usr/bin/python3

from flask import Flask
APP = Flask(__name__)

@APP.route("/")
def hello():
  return "Hello World!"

if __name__ == "__main__":
  APP.run()

Etape 3 afficheur de l'Image du jour

Maintenant que tout est configuré, vous pouvez commencer à écrire le code pour l'afficheur de l'Image du jour. L'Image du jour (Picture of the day - POTD), est une image mise à la une le temps d'une journée et affichée sur la page d'accueil de Wikipedia. Vous obtiendrez cette image à partir d'un modèle du wiki et elle changera chaque jour.

Récupérer la date du jour

La première chose à laquelle s'intéresser est de savoir simplement quel jour nous sommes. Parce que cette image change chaque jour, vous avez besoin de la date du jour pour accéder aux archives et obtenir une version stable de la bonne image. Pour cela, importez la classe Python date.

Puis définissez une nouvelle fonction index(). Index() va générer la page web en transmettant toutes les données associées à vos API appelées. Voir ici pour d'autres informations sur le fichier index.html que nous utiliserons comme modèle. Actuellement, index() doit contenir une variable représentant la date actuelle. Nous l'utiliserons bientôt pour créer une requête pour accéder à l'Image du jour.

#!/usr/bin/python3
from datetime import date
from flask import Flask, render_template

APP = Flask(__name__)

@APP.route("/")
def index():
  todays_date = date.today().isoformat()

if __name__ == "__main__":
  APP.run()

Appeler l'API Action

L'API Action fonctionne en renvoyant des données en réponse aux requêtes HTTP. Pour ce faire, importez la bibliothèque Python des requêtes.

Puis ajoutez deux nouvelles variables : SESSION = requests.Session() et ENDPOINT = "https://en.wikipedia.org/w/api.php". Vous allez utiliser l'objet SESSION pour faire des requêtes à l'URL ENDPOINT.

In a new function, fetch_potd(), call API:Images/fr to request the picture embedded within a protected POTD page (example). From this call, use the picture's filename to call API:Imageinfo/fr , and retrieve the image's source url. In this example, the second API call is handled in the helper function, fetch_image_src().

Wikipedia's archives lists dates by ISO standard format -- for instance, 2019-01-31, for 31 January, 2019. You can get the correct format by using the date method, isoformat().

def fetch_potd(cur_date):
  date_iso = cur_date.isoformat()
  title = "Template:POTD_protected/" + date_iso

  params = {
    "action": "query",
    "format": "json",
    "formatversion": "2",
    "prop": "images",
    "titles": title
  }

  response = SESSION.get(url = ENDPOINT, params = params)
  data = response.json()
  filename = data["query"]["pages"][0]["images"][0]["title"]
  image_page_url = "https://en.wikipedia.org/wiki/" + title
    
  image_data = {
    "filename": filename,
    "image_page_url": image_page_url,
    "image_src": fetch_image_src(filename),
    "date": date_iso
  }

  return image_data

def fetch_image_src(filename):
  params = {
    "action": "query",
    "format": "json",
    "prop": "imageinfo",
    "iiprop": "url",
    "titles": filename
  }

  response = SESSION.get(url = ENDPOINT, params = params)
  data = response.json()
  page = next(iter(data["query"]["pages"].values()))
  image_info = page["imageinfo"][0]
  image_url = image_info["url"]

  return image_url

Enfin modifiez index() pour appeler fetch_potd(). Importez render_template de flask, et faites que index() renvoie render_template("index.html", data=data).

{anchor|Displaying_the_page}

Afficher la page

A screenshot of the Picture of the Day Viewer available on the MediaWiki Code Samples repo, at GitHub
Ecran de l'application de l'afficheur de l'Image du jour

Flask templates mostly contain HTML markup, but they also use Jinja to render dynamic content. Jinja markup looks like this -- {{ variable }} -- and is used to inject Python variables or expressions into our basic page structure. Add some basic HTML 5 boilerplate and a few elements to index.html. Make sure to save it to a directory within your app, named /templates.

<!DOCTYPE html>
<html lang="en">
  <meta charset="utf-8">
  <title>Picture of the Day</title>
  <link rel="stylesheet" href="/static/style.css">

  <main>
    <h1>Picture of the day:</h1>
    <div class="card">
      <div class="potd">
        <h2>{{ data.filename }}</h2>
        <a href="{{ data.image_page_url }}" target="blank">
        <figure>
          <img src="{{ data.image_src }}">
          <figcaption>View on Wikipedia</figcaption>
        </figure>
        </a>
      </div>
      <div class = "date-container">
      <div class = "current-date">{{ data.date.strftime("%d %B %Y") }}</div>
    </div>
    </div>
</main>

Rendre interactif

Add a ‎<form> element to index.html, and give it the following submit button inputs: Back and Next. When either button is selected, the form will submit a POST request, and the selected value will be passed back to app.py. Cela va permettre aux utilisateurs de parcourir les archives des Images du jour.

Next, update app.py with a change_date() function, for setting the date presented to the user. Etendez également la route / pour gérer les requêtes POST à partir du formulaire. Pour permettre à app.py de lire le message POST de la requête, importez la classe Flask Request.

Code Python et HTML complet :

$HOME/picture-of-the-day-viewer/app.py
"""
    app.py
    MediaWiki Action API Code Samples

    Fetches Wikipedia Picture of the Day (POTD) and displays it on a webpage.
    Also allows users to go backward or forward a date to view other POTD.

    MIT License
"""

#!/usr/bin/python3

from datetime import date, timedelta
from flask import Flask, render_template, request
import requests

APP = Flask(__name__)
SESSION = requests.Session()
ENDPOINT = "https://en.wikipedia.org/w/api.php"
CURRENT_DATE = date.today()

@APP.route("/", methods=["GET", "POST"])
def index():
    """
    Requests data from Action API via 'fetch_potd' function & renders it on the
    index page accessible at '/'
    """

    if request.method == "POST":
        change_date()

    data = fetch_potd(CURRENT_DATE)

    return render_template("index.html", data=data)

def change_date():
    """
    Changes current date in response to input from the web form
    """

    global CURRENT_DATE

    user_input = request.form["change_date"]
    new_date = CURRENT_DATE
    last_date = date.today()
    first_date = date(year=2004, month=5, day=14)

    if user_input == "← Back":
        new_date = new_date - timedelta(days=1)
    elif user_input == "Next →":
        new_date = new_date + timedelta(days=1)

    if new_date > last_date or new_date < first_date:
        return

    CURRENT_DATE = new_date

def fetch_potd(cur_date):
    """
    Returns image data related to the current POTD
    """

    date_iso = cur_date.isoformat()
    title = "Template:POTD protected/" + date_iso

    params = {
        "action": "query",
        "format": "json",
        "formatversion": "2",
        "prop": "images",
        "titles": title
    }

    response = SESSION.get(url=ENDPOINT, params=params)
    data = response.json()

    filename = data["query"]["pages"][0]["images"][0]["title"]
    image_src = fetch_image_src(filename)
    image_page_url = "https://en.wikipedia.org/wiki/Template:POTD_protected/" + date_iso

    image_data = {
        "filename": filename,
        "image_src": image_src,
        "image_page_url": image_page_url,
        "date": cur_date
    }

    return image_data

def fetch_image_src(filename):
    """
    Returns the POTD's image url
    """

    params = {
        "action": "query",
        "format": "json",
        "prop": "imageinfo",
        "iiprop": "url",
        "titles": filename
    }

    response = SESSION.get(url=ENDPOINT, params=params)
    data = response.json()
    page = next(iter(data["query"]["pages"].values()))
    image_info = page["imageinfo"][0]
    image_url = image_info["url"]

    return image_url

if __name__ == "__main__":
    APP.run()
$HOME/picture-of-the-day-viewer/templates/index.html
<!DOCTYPE html>
<html lang="en">
  <meta charset="utf-8">
  <title>Picture of the Day</title>
  <link rel="stylesheet" href="/static/style.css">

  <main>
    <h1>Picture of the day:</h1>
    <div class="card">
      <div class="potd">
        <h2>{{ data.filename }}</h2>
        <a href="{{ data.image_page_url }}" target="blank">
        <figure>
          <img src="{{ data.image_src }}">
          <figcaption>View on Wikipedia</figcaption>
        </figure>
        </a>
      </div>
      <div class="date-container">
        <time class="current-date">{{ data.date.strftime("%d %B %Y") }}</time>
        <div class="date-navigator">
          <form action="/" method="POST">
            {% if data.date.strftime("%d %B %Y") == "14 May 2004" %}
            <input type="submit" name="change_date" value="← Back" disabled>
            {% else %}
            <input type="submit" name="change_date" value="← Back">
            {% endif %}
            {% if data.date == data.date.today() %}
            <input type="submit" name="change_date" value="Next →" disabled>
            {% else %}
            <input type="submit" name="change_date" value="Next →">
            {% endif %}
          </form>
        </div>
      </div>
    </div>
</main>

Mettre en forme votre application

Flask uses a directory, named static, to contain any helper files that stay the same throughout the lifecycle of the app. C'est un endroit adapté pour y mettre les feuilles de style ou les scripts supplémentaires. Our stylesheet will be using some colors and visual motifs based on the Wikimedia Style Guide. Ajoutez un fichier CSS dans $HOME/picture-of-the-day-viewer/static/style.css.

$HOME/picture-of-the-day-viewer/style.css
html {
    margin: 0;
    padding: 0;
    height: 100vh;
    width: 100vw;
}

body {
    margin: 0;
    background: #f8f9fa; /* light grey */
    font-family: Arial, Helvetica, sans-serif;
    font-size: 16px;
}

h1 {
    margin: 0;
    padding: 12px;
    background: #2a4b8d; /* dark blue */
    color: #ffffff;
}

h2 {
    margin-top: 8px;
    padding: 12px;
    font-size: 1em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    background: #f3f9ff; /* very light blue */
    border: 1px solid #2a4b8d; /* dark blue */
}

a {
    color: #3366cc; /* blue */
}

p {
    margin: 8px;
}

.card {
    position: relative;
    margin: auto;
    min-width: 200px;
    max-width: 67vw;
    height: 90vh;
    background: #ffffff;
    border-radius: 8px;
    box-shadow: 3px 6px 10px rgba(0, 0, 0, 0.16);
}

.potd {
    width: inherit;
    height: 60vh;
}

figure {
    width: 100%;
    margin: auto;
    text-align: center;
}

figure img {
    display: block;
    margin: 12px auto; 
    max-width: 64vw;
    max-height: 50vh;
    border: 1px solid#3366cc; /* blue */
}

figure a {
    margin: 8px;
}

.date-container {
    display: block;
    position: absolute;
    bottom: 0;
    left: 0;
    right:0;
    text-align: center;
    font-weight: bold;
}

.current-date {
    margin: 16px auto;
    font-size: 2em;
    background: #ffffff;
    color: #72777d; /* grey */
}

Étapes suivantes

  • Des questions à propos de ce tutoriel ? Posez les sur Discourse.
  • Contribuez en enregistrant l'application de démonstration que vous avez réalisée utilisant l'API MediaWiki, dans ce dépôt d'exemples de code.
  • Learn some ways to add descriptive text from the Picture of the day page:
    • API:Search/fr provides snippets which can be used as a link preview
    • action=cirrusdump can be used to obtain the whole parsed text from articles on Wikis that have the Cirrussearch extension installed (see example).

Voir aussi